IMDb: fix page parser by adding html hex entity conversion
[enigma2-plugins.git] / imdb / src / plugin.py
1 # -*- coding: UTF-8 -*-
2 from Plugins.Plugin import PluginDescriptor
3 from twisted.web.client import downloadPage
4 from enigma import ePicLoad, eServiceReference
5 from Screens.Screen import Screen
6 from Screens.EpgSelection import EPGSelection
7 from Screens.ChannelSelection import SimpleChannelSelection
8 from Components.ActionMap import ActionMap
9 from Components.Pixmap import Pixmap
10 from Components.Label import Label
11 from Components.ScrollLabel import ScrollLabel
12 from Components.Button import Button
13 from Components.AVSwitch import AVSwitch
14 from Components.MenuList import MenuList
15 from Components.Language import language
16 from Components.ProgressBar import ProgressBar
17 from Tools.Directories import resolveFilename, SCOPE_PLUGINS, SCOPE_SKIN_IMAGE
18 from os import environ as os_environ
19 import re
20 import htmlentitydefs
21 import urllib
22 import gettext
23
24 def localeInit():
25         lang = language.getLanguage()[:2] # getLanguage returns e.g. "fi_FI" for "language_country"
26         os_environ["LANGUAGE"] = lang # Enigma doesn't set this (or LC_ALL, LC_MESSAGES, LANG). gettext needs it!
27         gettext.bindtextdomain("IMDb", resolveFilename(SCOPE_PLUGINS, "Extensions/IMDb/locale"))
28
29 def _(txt):
30         t = gettext.dgettext("IMDb", txt)
31         if t == txt:
32                 print "[IMDb] fallback to default translation for", txt 
33                 t = gettext.gettext(txt)
34         return t
35
36 localeInit()
37 language.addCallback(localeInit)
38
39 class IMDBChannelSelection(SimpleChannelSelection):
40         def __init__(self, session):
41                 SimpleChannelSelection.__init__(self, session, _("Channel Selection"))
42                 self.skinName = "SimpleChannelSelection"
43
44                 self["ChannelSelectEPGActions"] = ActionMap(["ChannelSelectEPGActions"],
45                         {
46                                 "showEPGList": self.channelSelected
47                         }
48                 )
49
50         def channelSelected(self):
51                 ref = self.getCurrentSelection()
52                 if (ref.flags & 7) == 7:
53                         self.enterPath(ref)
54                 elif not (ref.flags & eServiceReference.isMarker):
55                         self.session.openWithCallback(
56                                 self.epgClosed,
57                                 IMDBEPGSelection,
58                                 ref,
59                                 openPlugin = False
60                         )
61
62         def epgClosed(self, ret = None):
63                 if ret:
64                         self.close(ret)
65
66 class IMDBEPGSelection(EPGSelection):
67         def __init__(self, session, ref, openPlugin = True):
68                 EPGSelection.__init__(self, session, ref)
69                 self.skinName = "EPGSelection"
70                 self["key_green"].setText(_("Lookup"))
71                 self.openPlugin = openPlugin
72
73         def infoKeyPressed(self):
74                 self.timerAdd()
75
76         def timerAdd(self):
77                 cur = self["list"].getCurrent()
78                 evt = cur[0]
79                 sref = cur[1]
80                 if not evt: 
81                         return
82
83                 if self.openPlugin:
84                         self.session.open(
85                                 IMDB,
86                                 evt.getEventName()
87                         )
88                 else:
89                         self.close(evt.getEventName())
90
91         def onSelectionChanged(self):
92                 pass
93
94 class IMDB(Screen):
95         skin = """
96                 <screen name="IMDB" position="90,95" size="560,420" title="Internet Movie Database Details Plugin" >
97                         <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" zPosition="0" size="140,40" transparent="1" alphatest="on" />
98                         <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" zPosition="0" size="140,40" transparent="1" alphatest="on" />
99                         <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" zPosition="0" size="140,40" transparent="1" alphatest="on" />
100                         <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" zPosition="0" size="140,40" transparent="1" alphatest="on" />
101                         <widget name="key_red" position="0,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#9f1313" transparent="1" />
102                         <widget name="key_green" position="140,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" />
103                         <widget name="key_yellow" position="280,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#a08500" transparent="1" />
104                         <widget name="key_blue" position="420,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#18188b" transparent="1" />
105                         <widget name="titellabel" position="10,40" size="330,45" valign="center" font="Regular;22"/>
106                         <widget name="detailslabel" position="105,90" size="445,140" font="Regular;18" />
107                         <widget name="castlabel" position="10,235" size="540,155" font="Regular;18" />
108                         <widget name="extralabel" position="10,40" size="540,350" font="Regular;18" />
109                         <widget name="ratinglabel" position="340,62" size="210,20" halign="center" font="Regular;18" foregroundColor="#f0b400"/>
110                         <widget name="statusbar" position="10,404" size="540,16" font="Regular;16" foregroundColor="#cccccc" />
111                         <widget name="poster" position="4,90" size="96,140" alphatest="on" />
112                         <widget name="menu" position="10,115" size="540,275" zPosition="3" scrollbarMode="showOnDemand" />
113                         <widget name="starsbg" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/IMDb/starsbar_empty.png" position="340,40" zPosition="0" size="210,21" transparent="1" alphatest="on" />
114                         <widget name="stars" position="340,40" size="210,21" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/IMDb/starsbar_filled.png" transparent="1" />
115                 </screen>"""
116
117         def __init__(self, session, eventName, args = None):
118                 self.skin = IMDB.skin
119                 Screen.__init__(self, session)
120
121                 self.eventName = eventName
122
123                 self.dictionary_init()
124
125                 self["poster"] = Pixmap()
126                 self.picload = ePicLoad()
127                 self.picload.PictureData.get().append(self.paintPosterPixmapCB)
128
129                 self["stars"] = ProgressBar()
130                 self["starsbg"] = Pixmap()
131                 self["stars"].hide()
132                 self["starsbg"].hide()
133                 self.ratingstars = -1
134
135                 self["titellabel"] = Label(_("The Internet Movie Database"))
136                 self["detailslabel"] = ScrollLabel("")
137                 self["castlabel"] = ScrollLabel("")
138                 self["extralabel"] = ScrollLabel("")
139                 self["statusbar"] = Label("")
140                 self["ratinglabel"] = Label("")
141                 self.resultlist = []
142                 self["menu"] = MenuList(self.resultlist)
143                 self["menu"].hide()
144
145                 self["key_red"] = Button(_("Exit"))
146                 self["key_green"] = Button("")
147                 self["key_yellow"] = Button("")
148                 self["key_blue"] = Button("")
149
150                 # 0 = multiple query selection menu page
151                 # 1 = movie info page
152                 # 2 = extra infos page
153                 self.Page = 0
154
155                 self["actions"] = ActionMap(["OkCancelActions", "ColorActions", "MovieSelectionActions", "DirectionActions"],
156                 {
157                         "ok": self.showDetails,
158                         "cancel": self.close,
159                         "down": self.pageDown,
160                         "up": self.pageUp,
161                         "red": self.close,
162                         "green": self.showMenu,
163                         "yellow": self.showDetails,
164                         "blue": self.showExtras,
165                         "contextMenu": self.openChannelSelection,
166                         "showEventInfo": self.showDetails
167                 }, -1)
168
169                 self.getIMDB()
170
171         def dictionary_init(self):
172                 syslang = language.getLanguage()
173                 if "de" not in syslang:
174                         self.IMDBlanguage = ""  # set to empty ("") for english version
175                 else:
176                         self.IMDBlanguage = "german." # it's a subdomain, so add a '.' at the end
177
178                 self.htmltags = re.compile('<.*?>')
179
180                 self.generalinfomask = re.compile(
181                 '<h1>(?P<title>.*?) <.*?</h1>.*?'
182                 '(?:.*?<h5>(?P<g_director>Regisseur|Directors?):</h5>.*?>(?P<director>.*?)</a>)*'
183                 '(?:.*?<h5>(?P<g_creator>Sch\S*?pfer|Creators?):</h5>.*?>(?P<creator>.*?)</a>)*'
184                 '(?:.*?<h5>(?P<g_seasons>Seasons):</h5>(?:.*?)<a href=\".*?\">(?P<seasons>\d+?)</a>\s+?(?:<a class|\|\s+?<a href="episodes#season-unknown))*'
185                 '(?:.*?<h5>(?P<g_writer>Drehbuch|Writer).*?</h5>.*?>(?P<writer>.*?)</a>)*'
186                 '(?:.*?<h5>(?P<g_premiere>Premiere|Release Date).*?</h5>\s.*?\n?(?P<premiere>.*?)\n\s.*?<)*'
187                 '(?:.*?<h5>(?P<g_alternativ>Alternativ|Also Known As):</h5>(?P<alternativ>.*?)<br>\s{0,8}<a.*?>(?:mehr|more))*'
188                 '(?:.*?<h5>(?P<g_country>Produktionsland|Country):</h5>.*?<a.*?>(?P<country>.*?)</a>(?:.*?mehr|\n</div>))*'
189                 , re.DOTALL)
190
191                 self.extrainfomask = re.compile(
192                 '(?:.*?<h5>(?P<g_tagline>Werbezeile|Tagline?):</h5>\n(?P<tagline>.+?)<)*'
193                 '(?:.*?<h5>(?P<g_outline>Kurzbeschreibung|Plot Outline):</h5>(?P<outline>.+?)<)*'
194                 '(?:.*?<h5>(?P<g_synopsis>Plot Synopsis):</h5>(?:.*?)(?:<a href=\".*?\">)*?(?P<synopsis>.+?)(?:</a>|</div>))*'
195                 '(?:.*?<h5>(?P<g_keywords>Plot Keywords):</h5>(?P<keywords>.+?)(?:mehr|more</a>|</div>))*'
196                 '(?:.*?<h5>(?P<g_awards>Filmpreise|Awards):</h5>(?P<awards>.+?)(?:mehr|more</a>|</div>))*'
197                 '(?:.*?<h5>(?P<g_runtime>L\S*?nge|Runtime):</h5>(?P<runtime>.+?)<)*'
198                 '(?:.*?<h5>(?P<g_language>Sprache|Language):</h5>(?P<language>.+?)</div>)*'
199                 '(?:.*?<h5>(?P<g_color>Farbe|Color):</h5>(?P<color>.+?)</div>)*'
200                 '(?:.*?<h5>(?P<g_aspect>Seitenverh\S*?ltnis|Aspect Ratio):</h5>(?P<aspect>.+?)(?:mehr|more</a>|</div>))*'
201                 '(?:.*?<h5>(?P<g_sound>Tonverfahren|Sound Mix):</h5>(?P<sound>.+?)</div>)*'
202                 '(?:.*?<h5>(?P<g_cert>Altersfreigabe|Certification):</h5>(?P<cert>.+?)</div>)*'
203                 '(?:.*?<h5>(?P<g_locations>Drehorte|Filming Locations):</h5>(?P<locations>.+?)(?:mehr|more</a>|</div>))*'
204                 '(?:.*?<h5>(?P<g_company>Firma|Company):</h5>(?P<company>.+?)(?:mehr|more</a>|</div>))*'
205                 '(?:.*?<h5>(?P<g_trivia>Dies und das|Trivia):</h5>(?P<trivia>.+?)(?:mehr|more</a>|</div>))*'
206                 '(?:.*?<h5>(?P<g_goofs>Pannen|Goofs):</h5>(?P<goofs>.+?)(?:mehr|more</a>|</div>))*'
207                 '(?:.*?<h5>(?P<g_quotes>Dialogzitate|Quotes):</h5>(?P<quotes>.+?)(?:mehr|more</a>|</div>))*'
208                 '(?:.*?<h5>(?P<g_connections>Bez\S*?ge zu anderen Titeln|Movie Connections):</h5>(?P<connections>.+?)(?:mehr|more</a>|</div>))*'
209                 '(?:.*?<h3>(?P<g_comments>Nutzerkommentare|User Comments)</h3>.*?<a href="/user/ur\d{7,7}/comments">(?P<commenter>.+?)\n</div>.*?<p>(?P<comment>.+?)</p>)*'
210                 , re.DOTALL)
211
212         def resetLabels(self):
213                 self["detailslabel"].setText("")
214                 self["ratinglabel"].setText("")
215                 self["titellabel"].setText("")
216                 self["castlabel"].setText("")
217                 self["titellabel"].setText("")
218                 self["extralabel"].setText("")
219                 self.ratingstars = -1
220
221         def pageUp(self):
222                 if self.Page == 0:
223                         self["menu"].instance.moveSelection(self["menu"].instance.moveUp)
224                 if self.Page == 1:
225                         self["castlabel"].pageUp()
226                         self["detailslabel"].pageUp()
227                 if self.Page == 2:
228                         self["extralabel"].pageUp()
229
230         def pageDown(self):
231                 if self.Page == 0:
232                         self["menu"].instance.moveSelection(self["menu"].instance.moveDown)
233                 if self.Page == 1:
234                         self["castlabel"].pageDown()
235                         self["detailslabel"].pageDown()
236                 if self.Page == 2:
237                         self["extralabel"].pageDown()
238
239         def showMenu(self):
240                 if ( self.Page is 1 or self.Page is 2 ) and self.resultlist:
241                         self["menu"].show()
242                         self["stars"].hide()
243                         self["starsbg"].hide()
244                         self["ratinglabel"].hide()
245                         self["castlabel"].hide()
246                         self["poster"].hide()
247                         self["extralabel"].hide()
248                         self["titellabel"].setText(_("Ambiguous results"))
249                         self["detailslabel"].setText(_("Please select the matching entry"))
250                         self["detailslabel"].show()
251                         self["key_blue"].setText("")
252                         self["key_green"].setText(_("Title Menu"))
253                         self["key_yellow"].setText(_("Details"))
254                         self.Page = 0
255
256         def showDetails(self):
257                 self["ratinglabel"].show()
258                 self["castlabel"].show()
259                 self["detailslabel"].show()
260
261                 if self.resultlist and self.Page == 0:
262                         link = self["menu"].getCurrent()[1]
263                         title = self["menu"].getCurrent()[0]
264                         self["statusbar"].setText(_("Re-Query IMDb: %s...") % (title))
265                         localfile = "/tmp/imdbquery2.html"
266                         fetchurl = "http://" + self.IMDBlanguage + "imdb.com/title/" + link
267                         print "[IMDB] downloading query " + fetchurl + " to " + localfile
268                         downloadPage(fetchurl,localfile).addCallback(self.IMDBquery2).addErrback(self.fetchFailed)
269                         self["menu"].hide()
270                         self.resetLabels()
271                         self.Page = 1
272
273                 if self.Page == 2:
274                         self["extralabel"].hide()
275                         self["poster"].show()
276                         if self.ratingstars > 0:
277                                 self["starsbg"].show()
278                                 self["stars"].show()
279                                 self["stars"].setValue(self.ratingstars)
280
281                         self.Page = 1
282
283         def showExtras(self):
284                 if self.Page == 1:
285                         self["extralabel"].show()
286                         self["detailslabel"].hide()
287                         self["castlabel"].hide()
288                         self["poster"].hide()
289                         self["stars"].hide()
290                         self["starsbg"].hide()
291                         self["ratinglabel"].hide()
292                         self.Page = 2
293
294         def openChannelSelection(self):
295                 self.session.openWithCallback(
296                         self.channelSelectionClosed,
297                         IMDBChannelSelection
298                 )
299
300         def channelSelectionClosed(self, ret = None):
301                 if ret:
302                         self.eventName = ret
303                         self.Page = 0
304                         self.resultlist = []
305                         self["menu"].hide()
306                         self["ratinglabel"].show()
307                         self["castlabel"].show()
308                         self["detailslabel"].show()
309                         self["poster"].hide()
310                         self["stars"].hide()
311                         self["starsbg"].hide()
312                         self.getIMDB()
313
314         def getIMDB(self):
315                 self.resetLabels()
316                 if self.eventName is "":
317                         s = self.session.nav.getCurrentService()
318                         info = s.info()
319                         event = info.getEvent(0) # 0 = now, 1 = next
320                         if event:
321                                 self.eventName = event.getEventName()
322                 if self.eventName is not "":
323                         self["statusbar"].setText(_("Query IMDb: %s...") % (self.eventName))
324                         event_quoted = urllib.quote(self.eventName.decode('utf8').encode('latin-1','ignore'))
325                         localfile = "/tmp/imdbquery.html"
326                         fetchurl = "http://" + self.IMDBlanguage + "imdb.com/find?q=" + event_quoted + "&s=tt&site=aka"
327                         print "[IMDB] Downloading Query " + fetchurl + " to " + localfile
328                         downloadPage(fetchurl,localfile).addCallback(self.IMDBquery).addErrback(self.fetchFailed)
329                 else:
330                         self["statusbar"].setText(_("Could't get Eventname"))
331
332         def fetchFailed(self,string):
333                 print "[IMDB] fetch failed " + string
334                 self["statusbar"].setText(_("IMDb Download failed"))
335
336         def html2utf8(self,in_html):
337                 htmlentitynumbermask = re.compile('(&#(\d{1,5}?);)')
338                 htmlentitynamemask = re.compile('(&(\D{1,5}?);)')
339                 entities = htmlentitynamemask.finditer(in_html)
340                 entitydict = {}
341
342                 for x in entities:
343                         entitydict[x.group(1)] = x.group(2)
344                 for key, name in entitydict.items():
345                         if key[0:3] == "&#x":
346                                 try:
347                                         entitydict[key] = "%d" % int(key[3:5], 16)
348                                 except:
349                                         print "[IMDb] html2utf8 entity hex->dec conversion error"
350                         else:
351                                 entitydict[key] = htmlentitydefs.name2codepoint[name]
352                 entities = htmlentitynumbermask.finditer(in_html)
353
354                 for x in entities:
355                         entitydict[x.group(1)] = x.group(2)
356                 for key, codepoint in entitydict.items():
357                         in_html = in_html.replace(key, (unichr(int(codepoint)).encode('latin-1')))
358                 self.inhtml = in_html.decode('latin-1').encode('utf8')
359
360         def IMDBquery(self,string):
361                 print "[IMDBquery]"
362                 self["statusbar"].setText(_("IMDb Download completed"))
363
364                 self.html2utf8(open("/tmp/imdbquery.html", "r").read())
365
366                 self.generalinfos = self.generalinfomask.search(self.inhtml)
367
368                 if self.generalinfos:
369                         self.IMDBparse()
370                 else:
371                         if re.search("<title>(?:IMDb.{0,9}Search|IMDb Titelsuche)</title>", self.inhtml):
372                                 searchresultmask = re.compile("<tr> <td.*?img src.*?>.*?<a href=\".*?/title/(tt\d{7,7})/\".*?>(.*?)</td>", re.DOTALL)
373                                 searchresults = searchresultmask.finditer(self.inhtml)
374                                 self.resultlist = [(self.htmltags.sub('',x.group(2)), x.group(1)) for x in searchresults]
375                                 self["menu"].l.setList(self.resultlist)
376                                 if len(self.resultlist) > 1:
377                                         self.Page = 1
378                                         self.showMenu()
379                                 else:
380                                         self["detailslabel"].setText(_("No IMDb match."))
381                                         self["statusbar"].setText(_("No IMDb match."))
382                         else:
383                                 splitpos = self.eventName.find('(')
384                                 if splitpos > 0 and self.eventName.endswith(')'):
385                                         self.eventName = self.eventName[splitpos+1:-1]
386                                         self["statusbar"].setText(_("Re-Query IMDb: %s...") % (self.eventName))
387                                         event_quoted = urllib.quote(self.eventName.decode('utf8').encode('latin-1','ignore'))
388                                         localfile = "/tmp/imdbquery.html"
389                                         fetchurl = "http://" + self.IMDBlanguage + "imdb.com/find?q=" + event_quoted + "&s=tt&site=aka"
390                                         print "[IMDB] Downloading Query " + fetchurl + " to " + localfile
391                                         downloadPage(fetchurl,localfile).addCallback(self.IMDBquery).addErrback(self.fetchFailed)
392                                 else:
393                                         self["detailslabel"].setText(_("IMDb query failed!"))
394
395         def IMDBquery2(self,string):
396                 self["statusbar"].setText(_("IMDb Re-Download completed"))
397                 self.html2utf8(open("/tmp/imdbquery2.html", "r").read())
398                 self.generalinfos = self.generalinfomask.search(self.inhtml)
399                 self.IMDBparse()
400
401         def IMDBparse(self):
402                 print "[IMDBparse]"
403                 self.Page = 1
404                 Detailstext = _("No details found.")
405                 if self.generalinfos:
406                         self["key_yellow"].setText(_("Details"))
407                         self["statusbar"].setText(_("IMDb Details parsed"))
408                         Titeltext = self.generalinfos.group("title")
409                         if len(Titeltext) > 57:
410                                 Titeltext = Titeltext[0:54] + "..."
411                         self["titellabel"].setText(Titeltext)
412
413                         Detailstext = ""
414
415                         genreblockmask = re.compile('<h5>Genre:</h5>(.*?)(?:mehr|more|</div>)', re.DOTALL)
416                         genreblock = genreblockmask.findall(self.inhtml)
417                         genremask = re.compile('(?:\">|\s)(.*?)(?:</a|\s)')
418                         if genreblock:
419                                 genres = genremask.finditer(genreblock[0])
420                                 if genres:
421                                         Detailstext += "Genre: "
422                                         for x in genres:
423                                                 Detailstext += x.group(1) + " "
424
425                         for category in ("director", "creator", "writer", "premiere", "seasons", "country"):
426                                 if self.generalinfos.group('g_'+category):
427                                         Detailstext += "\n" + self.generalinfos.group('g_'+category) + ": " + self.generalinfos.group(category)
428
429                         if self.generalinfos.group("alternativ"):
430                                 Detailstext += "\n" + self.generalinfos.group("g_alternativ") + ": " + self.htmltags.sub('',(self.generalinfos.group("alternativ").replace('\n','').replace("<br>",'\n').replace("  ",' ')))
431
432                         ratingmask = re.compile('<h5>(?P<g_rating>Nutzer-Bewertung|User Rating):</h5>.*?<b>(?P<rating>.*?)/10</b>', re.DOTALL)
433                         rating = ratingmask.search(self.inhtml)
434                         Ratingtext = _("no user rating yet")
435                         if rating:
436                                 Ratingtext = rating.group("g_rating") + ": " + rating.group("rating") + " / 10"
437                                 self.ratingstars = int(10*round(float(rating.group("rating").replace(',','.')),1))
438                                 self["stars"].show()
439                                 self["stars"].setValue(self.ratingstars)
440                                 self["starsbg"].show()
441                         self["ratinglabel"].setText(Ratingtext)
442                         castmask = re.compile('<td class="nm">.*?>(.*?)</a>.*?<td class="char">(?:<a.*?>)?(.*?)(?:</a>)?</td>', re.DOTALL)
443                         castresult = castmask.finditer(self.inhtml)
444                         if castresult:
445                                 Casttext = ""
446                                 for x in castresult:
447                                         Casttext += "\n" + self.htmltags.sub('', x.group(1))
448                                         if x.group(2):
449                                                 Casttext += _(" as ") + self.htmltags.sub('', x.group(2).replace('/ ...',''))
450                                 if Casttext is not "":
451                                         Casttext = _("Cast: ") + Casttext
452                                 else:
453                                         Casttext = _("No cast list found in the database.")
454                                 self["castlabel"].setText(Casttext)
455                         postermask = re.compile('<div class="photo">.*?<img .*? src=\"(http.*?)\" .*?>', re.DOTALL)
456                         posterurl = postermask.search(self.inhtml)
457                         if posterurl and posterurl.group(1).find("jpg") > 0:
458                                 posterurl = posterurl.group(1)
459                                 self["statusbar"].setText(_("Downloading Movie Poster: %s...") % (posterurl))
460                                 localfile = "/tmp/poster.jpg"
461                                 print "[IMDB] downloading poster " + posterurl + " to " + localfile
462                                 downloadPage(posterurl,localfile).addCallback(self.IMDBPoster).addErrback(self.fetchFailed)
463                         else:
464                                 self.IMDBPoster("kein Poster")
465                         extrainfos = self.extrainfomask.search(self.inhtml)
466
467                         if extrainfos:
468                                 Extratext = "Extra Info\n"
469
470                                 for category in ("tagline","outline","synopsis","keywords","awards","runtime","language","color","aspect","sound","cert","locations","company","trivia","goofs","quotes","connections"):
471                                         if extrainfos.group('g_'+category):
472                                                 Extratext += extrainfos.group('g_'+category) + ": " + self.htmltags.sub('',extrainfos.group(category).replace("\n",'').replace("<br>",'\n')) + "\n"
473                                 if extrainfos.group("g_comments"):
474                                         Extratext += extrainfos.group("g_comments") + " [" + self.htmltags.sub('',extrainfos.group("commenter")) + "]: " + self.htmltags.sub('',extrainfos.group("comment").replace("\n",' ')) + "\n"
475
476                                 self["extralabel"].setText(Extratext)
477                                 self["extralabel"].hide()
478                                 self["key_blue"].setText(_("Extra Info"))
479
480                 self["detailslabel"].setText(Detailstext)
481
482         def IMDBPoster(self,string):
483                 self["statusbar"].setText(_("IMDb Details parsed"))
484                 if not string:
485                         filename = "/tmp/poster.jpg"
486                 else:
487                         filename = resolveFilename(SCOPE_PLUGINS, "Extensions/IMDb/no_poster.png")
488                 sc = AVSwitch().getFramebufferScale()
489                 self.picload.setPara((self["poster"].instance.size().width(), self["poster"].instance.size().height(), sc[0], sc[1], False, 1, "#00000000"))
490                 self.picload.startDecode(filename)
491
492         def paintPosterPixmapCB(self, picInfo=None):
493                 ptr = self.picload.getData()
494                 if ptr != None:
495                         self["poster"].instance.setPixmap(ptr.__deref__())
496                         self["poster"].show()
497
498         def createSummary(self):
499                 return IMDbLCDScreen
500
501 class IMDbLCDScreen(Screen):
502         skin = """
503         <screen position="0,0" size="132,64" title="IMDB Plugin">
504                 <widget name="headline" position="4,0" size="128,22" font="Regular;20"/>
505                 <widget source="session.Event_Now" render="Label" position="6,26" size="120,34" font="Regular;14" >
506                         <convert type="EventName">Name</convert>
507                 </widget>
508         </screen>"""
509
510         def __init__(self, session, parent):
511                 Screen.__init__(self, session)
512                 self["headline"] = Label(_("IMDb Plugin"))
513
514 def eventinfo(session, servicelist, **kwargs):
515         ref = session.nav.getCurrentlyPlayingServiceReference()
516         session.open(IMDBEPGSelection, ref)
517
518 def main(session, eventName="", **kwargs):
519         session.open(IMDB, eventName)
520
521 def Plugins(**kwargs):
522         try:
523                 return [PluginDescriptor(name="IMDb Details",
524                                 description=_("Query details from the Internet Movie Database"),
525                                 icon="imdb.png",
526                                 where = PluginDescriptor.WHERE_PLUGINMENU,
527                                 fnc = main),
528                                 PluginDescriptor(name="IMDb Details",
529                                 description=_("Query details from the Internet Movie Database"),
530                                 where = PluginDescriptor.WHERE_EVENTINFO,
531                                 fnc = eventinfo)
532                                 ]
533         except AttributeError:
534                 wherelist = [PluginDescriptor.WHERE_EXTENSIONSMENU, PluginDescriptor.WHERE_PLUGINMENU]
535                 return PluginDescriptor(name="IMDb Details",
536                                 description=_("Query details from the Internet Movie Database"),
537                                 icon="imdb.png",
538                                 where = wherelist,
539                                 fnc=main)