regular expression fixes...
[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, callbackNeeded=False):
118                 Screen.__init__(self, session)
119
120                 self.eventName = eventName
121                 
122                 self.callbackNeeded = callbackNeeded
123                 self.callbackData = ""
124                 self.callbackGenre = ""
125
126                 self.dictionary_init()
127
128                 self["poster"] = Pixmap()
129                 self.picload = ePicLoad()
130                 self.picload.PictureData.get().append(self.paintPosterPixmapCB)
131
132                 self["stars"] = ProgressBar()
133                 self["starsbg"] = Pixmap()
134                 self["stars"].hide()
135                 self["starsbg"].hide()
136                 self.ratingstars = -1
137
138                 self["titellabel"] = Label(_("The Internet Movie Database"))
139                 self["detailslabel"] = ScrollLabel("")
140                 self["castlabel"] = ScrollLabel("")
141                 self["extralabel"] = ScrollLabel("")
142                 self["statusbar"] = Label("")
143                 self["ratinglabel"] = Label("")
144                 self.resultlist = []
145                 self["menu"] = MenuList(self.resultlist)
146                 self["menu"].hide()
147
148                 self["key_red"] = Button(_("Exit"))
149                 self["key_green"] = Button("")
150                 self["key_yellow"] = Button("")
151                 self["key_blue"] = Button("")
152
153                 # 0 = multiple query selection menu page
154                 # 1 = movie info page
155                 # 2 = extra infos page
156                 self.Page = 0
157
158                 self["actions"] = ActionMap(["OkCancelActions", "ColorActions", "MovieSelectionActions", "DirectionActions"],
159                 {
160                         "ok": self.showDetails,
161                         "cancel": self.exit,
162                         "down": self.pageDown,
163                         "up": self.pageUp,
164                         "red": self.exit,
165                         "green": self.showMenu,
166                         "yellow": self.showDetails,
167                         "blue": self.showExtras,
168                         "contextMenu": self.openChannelSelection,
169                         "showEventInfo": self.showDetails
170                 }, -1)
171
172                 self.getIMDB()
173
174         def exit(self):
175                 if self.callbackNeeded:
176                         self.close([self.callbackData, self.callbackGenre])
177                 else:
178                         self.close()
179
180         def dictionary_init(self):
181                 syslang = language.getLanguage()
182                 if "de" not in syslang:
183                         self.IMDBlanguage = ""  # set to empty ("") for english version
184                 else:
185                         self.IMDBlanguage = "german." # it's a subdomain, so add a '.' at the end
186
187                 self.htmltags = re.compile('<.*?>')
188
189                 self.generalinfomask = re.compile(
190                 '<h1>(?P<title>.*?) <.*?</h1>.*?'
191                 '(?:.*?<h5>(?P<g_director>Regisseur|Directors?):</h5>.*?<a href=\".*?\">(?P<director>.*?)</a>)*'
192                 '(?:.*?<h5>(?P<g_creator>Sch\S*?pfer|Creators?):</h5>.*?<a href=\".*?\">(?P<creator>.*?)</a>)*'
193                 '(?:.*?<h5>(?P<g_seasons>Seasons):</h5>(?:.*?)<a href=\".*?\">(?P<seasons>\d+?)</a>\s+?(?:<a class|\|\s+?<a href="episodes#season-unknown))*'
194                 '(?:.*?<h5>(?P<g_writer>Drehbuch|Writer).*?</h5>.*?<a href=\".*?\">(?P<writer>.*?)</a>)*'
195                 '(?:.*?<h5>(?P<g_premiere>Premiere|Release Date).*?</h5>\s+<div.*?>\s?(?P<premiere>.*?)\n\s.*?<)*'
196                 '(?:.*?<h5>(?P<g_alternativ>Auch bekannt als|Also Known As):</h5><div.*?>\s*(?P<alternativ>.*?)<br>\s{0,8}<a.*?>(?:mehr|more))*'
197                 '(?:.*?<h5>(?P<g_country>Land|Country):</h5>\s+<div.*?>(?P<country>.*?)</div>(?:.*?mehr|\s+?</div>))*'
198                 , re.DOTALL)
199
200                 self.extrainfomask = re.compile(
201                 '(?:.*?<h5>(?P<g_tagline>Werbezeile|Tagline?):</h5>\n(?P<tagline>.+?)<)*'
202                 '(?:.*?<h5>(?P<g_outline>Kurzbeschreibung|Plot Outline):</h5>(?P<outline>.+?)<)*'
203                 '(?:.*?<h5>(?P<g_synopsis>Plot Synopsis):</h5>(?:.*?)(?:<a href=\".*?\">)*?(?P<synopsis>.+?)(?:</a>|</div>))*'
204                 '(?:.*?<h5>(?P<g_keywords>Plot Keywords):</h5>(?P<keywords>.+?)(?:mehr|more</a>|</div>))*'
205                 '(?:.*?<h5>(?P<g_awards>Filmpreise|Awards):</h5>(?P<awards>.+?)(?:mehr|more</a>|</div>))*'
206                 '(?:.*?<h5>(?P<g_runtime>L\S*?nge|Runtime):</h5>(?P<runtime>.+?)</div>)*'
207                 '(?:.*?<h5>(?P<g_language>Sprache|Language):</h5>(?P<language>.+?)</div>)*'
208                 '(?:.*?<h5>(?P<g_color>Farbe|Color):</h5>(?P<color>.+?)</div>)*'
209                 '(?:.*?<h5>(?P<g_aspect>Seitenverh\S*?ltnis|Aspect Ratio):</h5>(?P<aspect>.+?)(?:mehr|more</a>|</div>))*'
210                 '(?:.*?<h5>(?P<g_sound>Tonverfahren|Sound Mix):</h5>(?P<sound>.+?)</div>)*'
211                 '(?:.*?<h5>(?P<g_cert>Altersfreigabe|Certification):</h5>(?P<cert>.+?)</div>)*'
212                 '(?:.*?<h5>(?P<g_locations>Drehorte|Filming Locations):</h5>(?P<locations>.+?)(?:mehr|more</a>|</div>))*'
213                 '(?:.*?<h5>(?P<g_company>Firma|Company):</h5>(?P<company>.+?)(?:mehr|more</a>|</div>))*'
214                 '(?:.*?<h5>(?P<g_trivia>Dies und das|Trivia):</h5>(?P<trivia>.+?)(?:mehr|more</a>|</div>))*'
215                 '(?:.*?<h5>(?P<g_goofs>Pannen|Goofs):</h5>(?P<goofs>.+?)(?:mehr|more</a>|</div>))*'
216                 '(?:.*?<h5>(?P<g_quotes>Dialogzitate|Quotes):</h5>(?P<quotes>.+?)(?:mehr|more</a>|</div>))*'
217                 '(?:.*?<h5>(?P<g_connections>Bez\S*?ge zu anderen Titeln|Movie Connections):</h5>(?P<connections>.+?)(?:mehr|more</a>|</div>))*'
218                 '(?:.*?<h3>(?P<g_comments>Nutzerkommentare|User Comments)</h3>.*?<a href="/user/ur\d{7,7}/comments">(?P<commenter>.+?)\n</div>.*?<p>(?P<comment>.+?)</p>)*'
219                 , re.DOTALL)
220
221         def resetLabels(self):
222                 self["detailslabel"].setText("")
223                 self["ratinglabel"].setText("")
224                 self["titellabel"].setText("")
225                 self["castlabel"].setText("")
226                 self["titellabel"].setText("")
227                 self["extralabel"].setText("")
228                 self.ratingstars = -1
229
230         def pageUp(self):
231                 if self.Page == 0:
232                         self["menu"].instance.moveSelection(self["menu"].instance.moveUp)
233                 if self.Page == 1:
234                         self["castlabel"].pageUp()
235                         self["detailslabel"].pageUp()
236                 if self.Page == 2:
237                         self["extralabel"].pageUp()
238
239         def pageDown(self):
240                 if self.Page == 0:
241                         self["menu"].instance.moveSelection(self["menu"].instance.moveDown)
242                 if self.Page == 1:
243                         self["castlabel"].pageDown()
244                         self["detailslabel"].pageDown()
245                 if self.Page == 2:
246                         self["extralabel"].pageDown()
247
248         def showMenu(self):
249                 if ( self.Page is 1 or self.Page is 2 ) and self.resultlist:
250                         self["menu"].show()
251                         self["stars"].hide()
252                         self["starsbg"].hide()
253                         self["ratinglabel"].hide()
254                         self["castlabel"].hide()
255                         self["poster"].hide()
256                         self["extralabel"].hide()
257                         self["titellabel"].setText(_("Ambiguous results"))
258                         self["detailslabel"].setText(_("Please select the matching entry"))
259                         self["detailslabel"].show()
260                         self["key_blue"].setText("")
261                         self["key_green"].setText(_("Title Menu"))
262                         self["key_yellow"].setText(_("Details"))
263                         self.Page = 0
264
265         def showDetails(self):
266                 self["ratinglabel"].show()
267                 self["castlabel"].show()
268                 self["detailslabel"].show()
269
270                 if self.resultlist and self.Page == 0:
271                         link = self["menu"].getCurrent()[1]
272                         title = self["menu"].getCurrent()[0]
273                         self["statusbar"].setText(_("Re-Query IMDb: %s...") % (title))
274                         localfile = "/tmp/imdbquery2.html"
275                         fetchurl = "http://" + self.IMDBlanguage + "imdb.com/title/" + link
276                         print "[IMDB] downloading query " + fetchurl + " to " + localfile
277                         downloadPage(fetchurl,localfile).addCallback(self.IMDBquery2).addErrback(self.fetchFailed)
278                         self["menu"].hide()
279                         self.resetLabels()
280                         self.Page = 1
281
282                 if self.Page == 2:
283                         self["extralabel"].hide()
284                         self["poster"].show()
285                         if self.ratingstars > 0:
286                                 self["starsbg"].show()
287                                 self["stars"].show()
288                                 self["stars"].setValue(self.ratingstars)
289
290                         self.Page = 1
291
292         def showExtras(self):
293                 if self.Page == 1:
294                         self["extralabel"].show()
295                         self["detailslabel"].hide()
296                         self["castlabel"].hide()
297                         self["poster"].hide()
298                         self["stars"].hide()
299                         self["starsbg"].hide()
300                         self["ratinglabel"].hide()
301                         self.Page = 2
302
303         def openChannelSelection(self):
304                 self.session.openWithCallback(
305                         self.channelSelectionClosed,
306                         IMDBChannelSelection
307                 )
308
309         def channelSelectionClosed(self, ret = None):
310                 if ret:
311                         self.eventName = ret
312                         self.Page = 0
313                         self.resultlist = []
314                         self["menu"].hide()
315                         self["ratinglabel"].show()
316                         self["castlabel"].show()
317                         self["detailslabel"].show()
318                         self["poster"].hide()
319                         self["stars"].hide()
320                         self["starsbg"].hide()
321                         self.getIMDB()
322
323         def getIMDB(self):
324                 self.resetLabels()
325                 if self.eventName is "":
326                         s = self.session.nav.getCurrentService()
327                         info = s.info()
328                         event = info.getEvent(0) # 0 = now, 1 = next
329                         if event:
330                                 self.eventName = event.getEventName()
331                 if self.eventName is not "":
332                         self["statusbar"].setText(_("Query IMDb: %s...") % (self.eventName))
333                         event_quoted = urllib.quote(self.eventName.decode('utf8').encode('latin-1','ignore'))
334                         localfile = "/tmp/imdbquery.html"
335                         fetchurl = "http://" + self.IMDBlanguage + "imdb.com/find?q=" + event_quoted + "&s=tt&site=aka"
336                         print "[IMDB] Downloading Query " + fetchurl + " to " + localfile
337                         downloadPage(fetchurl,localfile).addCallback(self.IMDBquery).addErrback(self.fetchFailed)
338                 else:
339                         self["statusbar"].setText(_("Could't get Eventname"))
340
341         def fetchFailed(self,string):
342                 print "[IMDB] fetch failed", string
343                 self["statusbar"].setText(_("IMDb Download failed"))
344
345         def html2utf8(self,in_html):
346                 htmlentitynumbermask = re.compile('(&#(\d{1,5}?);)')
347                 htmlentityhexmask = re.compile('(&#x([0-9A-Fa-f]{2,2}?);)')
348                 htmlentitynamemask = re.compile('(&([^#]\D{1,5}?);)')
349                 entitydict = {}
350                 entityhexdict = {}
351                 entities = htmlentitynamemask.finditer(in_html)
352
353                 for x in entities:
354                         entitydict[x.group(1)] = x.group(2)
355                 for key, name in entitydict.items():
356                         entitydict[key] = htmlentitydefs.name2codepoint[name]
357                 entities = htmlentityhexmask.finditer(in_html)
358
359                 for x in entities:
360                         entityhexdict[x.group(1)] = x.group(2)
361
362                 for key, name in entityhexdict.items():
363                         entitydict[key] = "%d" % int(key[3:5], 16)
364                         print "key:", key, "before:", name, "after:", entitydict[key]
365                 
366                 entities = htmlentitynumbermask.finditer(in_html)
367                 for x in entities:
368                         entitydict[x.group(1)] = x.group(2)
369                 for key, codepoint in entitydict.items():
370                         in_html = in_html.replace(key, (unichr(int(codepoint)).encode('latin-1')))
371                 self.inhtml = in_html.decode('latin-1').encode('utf8')
372
373         def IMDBquery(self,string):
374                 print "[IMDBquery]"
375                 self["statusbar"].setText(_("IMDb Download completed"))
376
377                 self.html2utf8(open("/tmp/imdbquery.html", "r").read())
378
379                 self.generalinfos = self.generalinfomask.search(self.inhtml)
380
381                 if self.generalinfos:
382                         self.IMDBparse()
383                 else:
384                         if re.search("<title>(?:IMDb.{0,9}Search|IMDb Titelsuche)</title>", self.inhtml):
385                                 searchresultmask = re.compile("<tr> <td.*?img src.*?>.*?<a href=\".*?/title/(tt\d{7,7})/\".*?>(.*?)</td>", re.DOTALL)
386                                 searchresults = searchresultmask.finditer(self.inhtml)
387                                 self.resultlist = [(self.htmltags.sub('',x.group(2)), x.group(1)) for x in searchresults]
388                                 self["menu"].l.setList(self.resultlist)
389                                 if len(self.resultlist) > 1:
390                                         self.Page = 1
391                                         self.showMenu()
392                                 else:
393                                         self["detailslabel"].setText(_("No IMDb match."))
394                                         self["statusbar"].setText(_("No IMDb match."))
395                         else:
396                                 splitpos = self.eventName.find('(')
397                                 if splitpos > 0 and self.eventName.endswith(')'):
398                                         self.eventName = self.eventName[splitpos+1:-1]
399                                         self["statusbar"].setText(_("Re-Query IMDb: %s...") % (self.eventName))
400                                         event_quoted = urllib.quote(self.eventName.decode('utf8').encode('latin-1','ignore'))
401                                         localfile = "/tmp/imdbquery.html"
402                                         fetchurl = "http://" + self.IMDBlanguage + "imdb.com/find?q=" + event_quoted + "&s=tt&site=aka"
403                                         print "[IMDB] Downloading Query " + fetchurl + " to " + localfile
404                                         downloadPage(fetchurl,localfile).addCallback(self.IMDBquery).addErrback(self.fetchFailed)
405                                 else:
406                                         self["detailslabel"].setText(_("IMDb query failed!"))
407
408         def IMDBquery2(self,string):
409                 self["statusbar"].setText(_("IMDb Re-Download completed"))
410                 self.html2utf8(open("/tmp/imdbquery2.html", "r").read())
411                 self.generalinfos = self.generalinfomask.search(self.inhtml)
412                 self.IMDBparse()
413
414         def IMDBparse(self):
415                 print "[IMDBparse]"
416                 self.Page = 1
417                 Detailstext = _("No details found.")
418                 if self.generalinfos:
419                         self["key_yellow"].setText(_("Details"))
420                         self["statusbar"].setText(_("IMDb Details parsed"))
421                         Titeltext = self.generalinfos.group("title")
422                         if len(Titeltext) > 57:
423                                 Titeltext = Titeltext[0:54] + "..."
424                         self["titellabel"].setText(Titeltext)
425
426                         Detailstext = ""
427
428                         genreblockmask = re.compile('<h5>Genre:</h5>\n<p>\s+?(.*?)\s+?(?:mehr|more|</p|<a class|</div>)', re.DOTALL)
429                         genreblock = genreblockmask.findall(self.inhtml)
430                         if genreblock:
431                                 genres = self.htmltags.sub('', genreblock[0])
432                                 if genres:
433                                         Detailstext += "Genre: "
434                                         Detailstext += genres
435                                         self.callbackGenre = genres
436
437                         for category in ("director", "creator", "writer", "premiere", "seasons"):
438                                 if self.generalinfos.group('g_'+category):
439                                         Detailstext += "\n" + self.generalinfos.group('g_'+category) + ": " + self.generalinfos.group(category)
440
441                         if self.generalinfos.group("country"):
442                                 Detailstext += "\n" + self.generalinfos.group("g_country") + ": " + self.htmltags.sub('', self.generalinfos.group("country").replace('\n','').replace("<br>",'\n').replace("  ",' '))
443
444                         if self.generalinfos.group("alternativ"):
445                                 Detailstext += "\n" + self.generalinfos.group("g_alternativ") + ": " + self.htmltags.sub('', self.generalinfos.group("alternativ").replace('\n','').replace("<br>",'\n').replace("  ",' '))
446
447                         ratingmask = re.compile('<h5>(?P<g_rating>Nutzer-Bewertung|User Rating):</h5>.*?<b>(?P<rating>.*?)/10</b>', re.DOTALL)
448                         rating = ratingmask.search(self.inhtml)
449                         Ratingtext = _("no user rating yet")
450                         if rating:
451                                 Ratingtext = rating.group("g_rating") + ": " + rating.group("rating") + " / 10"
452                                 self.ratingstars = int(10*round(float(rating.group("rating").replace(',','.')),1))
453                                 self["stars"].show()
454                                 self["stars"].setValue(self.ratingstars)
455                                 self["starsbg"].show()
456                         self["ratinglabel"].setText(Ratingtext)
457                         castmask = re.compile('<td class="nm">.*?>(.*?)</a>.*?<td class="char">(?:<a.*?>)?(.*?)(?:</a>)?</td>', re.DOTALL)
458                         castresult = castmask.finditer(self.inhtml)
459                         if castresult:
460                                 Casttext = ""
461                                 for x in castresult:
462                                         Casttext += "\n" + self.htmltags.sub('', x.group(1))
463                                         if x.group(2):
464                                                 Casttext += _(" as ") + self.htmltags.sub('', x.group(2).replace('/ ...',''))
465                                 if Casttext is not "":
466                                         Casttext = _("Cast: ") + Casttext
467                                 else:
468                                         Casttext = _("No cast list found in the database.")
469                                 self["castlabel"].setText(Casttext)
470                         postermask = re.compile('<div class="photo">.*?<img .*? src=\"(http.*?)\" .*?>', re.DOTALL)
471                         posterurl = postermask.search(self.inhtml)
472                         if posterurl and posterurl.group(1).find("jpg") > 0:
473                                 posterurl = posterurl.group(1)
474                                 self["statusbar"].setText(_("Downloading Movie Poster: %s...") % (posterurl))
475                                 localfile = "/tmp/poster.jpg"
476                                 print "[IMDB] downloading poster " + posterurl + " to " + localfile
477                                 downloadPage(posterurl,localfile).addCallback(self.IMDBPoster).addErrback(self.fetchFailed)
478                         else:
479                                 self.IMDBPoster("kein Poster")
480                         extrainfos = self.extrainfomask.search(self.inhtml)
481
482                         if extrainfos:
483                                 Extratext = "Extra Info\n"
484
485                                 for category in ("tagline","outline","synopsis","keywords","awards","runtime","language","color","aspect","sound","cert","locations","company","trivia","goofs","quotes","connections"):
486                                         if extrainfos.group('g_'+category):
487                                                 Extratext += extrainfos.group('g_'+category) + ": " + self.htmltags.sub('',extrainfos.group(category).replace("\n",'').replace("<br>",'\n')) + "\n"
488                                 if extrainfos.group("g_comments"):
489                                         stripmask = re.compile('\s{2,}', re.DOTALL)
490                                         Extratext += extrainfos.group("g_comments") + " [" + stripmask.sub(' ', self.htmltags.sub('',extrainfos.group("commenter"))) + "]: " + self.htmltags.sub('',extrainfos.group("comment").replace("\n",' ')) + "\n"
491
492                                 self["extralabel"].setText(Extratext)
493                                 self["extralabel"].hide()
494                                 self["key_blue"].setText(_("Extra Info"))
495
496                 self["detailslabel"].setText(Detailstext)
497                 self.callbackData = Detailstext
498
499         def IMDBPoster(self,string):
500                 self["statusbar"].setText(_("IMDb Details parsed"))
501                 if not string:
502                         filename = "/tmp/poster.jpg"
503                 else:
504                         filename = resolveFilename(SCOPE_PLUGINS, "Extensions/IMDb/no_poster.png")
505                 sc = AVSwitch().getFramebufferScale()
506                 self.picload.setPara((self["poster"].instance.size().width(), self["poster"].instance.size().height(), sc[0], sc[1], False, 1, "#00000000"))
507                 self.picload.startDecode(filename)
508
509         def paintPosterPixmapCB(self, picInfo=None):
510                 ptr = self.picload.getData()
511                 if ptr != None:
512                         self["poster"].instance.setPixmap(ptr.__deref__())
513                         self["poster"].show()
514
515         def createSummary(self):
516                 return IMDbLCDScreen
517
518 class IMDbLCDScreen(Screen):
519         skin = """
520         <screen position="0,0" size="132,64" title="IMDB Plugin">
521                 <widget name="headline" position="4,0" size="128,22" font="Regular;20"/>
522                 <widget source="session.Event_Now" render="Label" position="6,26" size="120,34" font="Regular;14" >
523                         <convert type="EventName">Name</convert>
524                 </widget>
525         </screen>"""
526
527         def __init__(self, session, parent):
528                 Screen.__init__(self, session)
529                 self["headline"] = Label(_("IMDb Plugin"))
530
531 def eventinfo(session, servicelist, **kwargs):
532         ref = session.nav.getCurrentlyPlayingServiceReference()
533         session.open(IMDBEPGSelection, ref)
534
535 def main(session, eventName="", **kwargs):
536         session.open(IMDB, eventName)
537
538 def Plugins(**kwargs):
539         try:
540                 return [PluginDescriptor(name="IMDb Details",
541                                 description=_("Query details from the Internet Movie Database"),
542                                 icon="imdb.png",
543                                 where = PluginDescriptor.WHERE_PLUGINMENU,
544                                 fnc = main),
545                                 PluginDescriptor(name="IMDb Details",
546                                 description=_("Query details from the Internet Movie Database"),
547                                 where = PluginDescriptor.WHERE_EVENTINFO,
548                                 fnc = eventinfo)
549                                 ]
550         except AttributeError:
551                 wherelist = [PluginDescriptor.WHERE_EXTENSIONSMENU, PluginDescriptor.WHERE_PLUGINMENU]
552                 return PluginDescriptor(name="IMDb Details",
553                                 description=_("Query details from the Internet Movie Database"),
554                                 icon="imdb.png",
555                                 where = wherelist,
556                                 fnc=main)