IMDb: improve entity converter
[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                 htmlentityhexmask = re.compile('(&#x([0-9A-Fa-f]{2,2}?);)')
339                 htmlentitynamemask = re.compile('(&([^#]\D{1,5}?);)')
340                 entitydict = {}
341                 entityhexdict = {}
342                 entities = htmlentitynamemask.finditer(in_html)
343
344                 for x in entities:
345                         entitydict[x.group(1)] = x.group(2)
346                 for key, name in entitydict.items():
347                         entitydict[key] = htmlentitydefs.name2codepoint[name]
348                 entities = htmlentityhexmask.finditer(in_html)
349
350                 for x in entities:
351                         entityhexdict[x.group(1)] = x.group(2)
352
353                 for key, name in entityhexdict.items():
354                         entitydict[key] = "%d" % int(key[3:5], 16)
355                         print "key:", key, "before:", name, "after:", entitydict[key]
356                 
357                 entities = htmlentitynumbermask.finditer(in_html)
358                 for x in entities:
359                         entitydict[x.group(1)] = x.group(2)
360                 for key, codepoint in entitydict.items():
361                         in_html = in_html.replace(key, (unichr(int(codepoint)).encode('latin-1')))
362                 self.inhtml = in_html.decode('latin-1').encode('utf8')
363
364         def IMDBquery(self,string):
365                 print "[IMDBquery]"
366                 self["statusbar"].setText(_("IMDb Download completed"))
367
368                 self.html2utf8(open("/tmp/imdbquery.html", "r").read())
369
370                 self.generalinfos = self.generalinfomask.search(self.inhtml)
371
372                 if self.generalinfos:
373                         self.IMDBparse()
374                 else:
375                         if re.search("<title>(?:IMDb.{0,9}Search|IMDb Titelsuche)</title>", self.inhtml):
376                                 searchresultmask = re.compile("<tr> <td.*?img src.*?>.*?<a href=\".*?/title/(tt\d{7,7})/\".*?>(.*?)</td>", re.DOTALL)
377                                 searchresults = searchresultmask.finditer(self.inhtml)
378                                 self.resultlist = [(self.htmltags.sub('',x.group(2)), x.group(1)) for x in searchresults]
379                                 self["menu"].l.setList(self.resultlist)
380                                 if len(self.resultlist) > 1:
381                                         self.Page = 1
382                                         self.showMenu()
383                                 else:
384                                         self["detailslabel"].setText(_("No IMDb match."))
385                                         self["statusbar"].setText(_("No IMDb match."))
386                         else:
387                                 splitpos = self.eventName.find('(')
388                                 if splitpos > 0 and self.eventName.endswith(')'):
389                                         self.eventName = self.eventName[splitpos+1:-1]
390                                         self["statusbar"].setText(_("Re-Query IMDb: %s...") % (self.eventName))
391                                         event_quoted = urllib.quote(self.eventName.decode('utf8').encode('latin-1','ignore'))
392                                         localfile = "/tmp/imdbquery.html"
393                                         fetchurl = "http://" + self.IMDBlanguage + "imdb.com/find?q=" + event_quoted + "&s=tt&site=aka"
394                                         print "[IMDB] Downloading Query " + fetchurl + " to " + localfile
395                                         downloadPage(fetchurl,localfile).addCallback(self.IMDBquery).addErrback(self.fetchFailed)
396                                 else:
397                                         self["detailslabel"].setText(_("IMDb query failed!"))
398
399         def IMDBquery2(self,string):
400                 self["statusbar"].setText(_("IMDb Re-Download completed"))
401                 self.html2utf8(open("/tmp/imdbquery2.html", "r").read())
402                 self.generalinfos = self.generalinfomask.search(self.inhtml)
403                 self.IMDBparse()
404
405         def IMDBparse(self):
406                 print "[IMDBparse]"
407                 self.Page = 1
408                 Detailstext = _("No details found.")
409                 if self.generalinfos:
410                         self["key_yellow"].setText(_("Details"))
411                         self["statusbar"].setText(_("IMDb Details parsed"))
412                         Titeltext = self.generalinfos.group("title")
413                         if len(Titeltext) > 57:
414                                 Titeltext = Titeltext[0:54] + "..."
415                         self["titellabel"].setText(Titeltext)
416
417                         Detailstext = ""
418
419                         genreblockmask = re.compile('<h5>Genre:</h5>(.*?)(?:mehr|more|</div>)', re.DOTALL)
420                         genreblock = genreblockmask.findall(self.inhtml)
421                         genremask = re.compile('(?:\">|\s)(.*?)(?:</a|\s)')
422                         if genreblock:
423                                 genres = genremask.finditer(genreblock[0])
424                                 if genres:
425                                         Detailstext += "Genre: "
426                                         for x in genres:
427                                                 Detailstext += x.group(1) + " "
428
429                         for category in ("director", "creator", "writer", "premiere", "seasons", "country"):
430                                 if self.generalinfos.group('g_'+category):
431                                         Detailstext += "\n" + self.generalinfos.group('g_'+category) + ": " + self.generalinfos.group(category)
432
433                         if self.generalinfos.group("alternativ"):
434                                 Detailstext += "\n" + self.generalinfos.group("g_alternativ") + ": " + self.htmltags.sub('',(self.generalinfos.group("alternativ").replace('\n','').replace("<br>",'\n').replace("  ",' ')))
435
436                         ratingmask = re.compile('<h5>(?P<g_rating>Nutzer-Bewertung|User Rating):</h5>.*?<b>(?P<rating>.*?)/10</b>', re.DOTALL)
437                         rating = ratingmask.search(self.inhtml)
438                         Ratingtext = _("no user rating yet")
439                         if rating:
440                                 Ratingtext = rating.group("g_rating") + ": " + rating.group("rating") + " / 10"
441                                 self.ratingstars = int(10*round(float(rating.group("rating").replace(',','.')),1))
442                                 self["stars"].show()
443                                 self["stars"].setValue(self.ratingstars)
444                                 self["starsbg"].show()
445                         self["ratinglabel"].setText(Ratingtext)
446                         castmask = re.compile('<td class="nm">.*?>(.*?)</a>.*?<td class="char">(?:<a.*?>)?(.*?)(?:</a>)?</td>', re.DOTALL)
447                         castresult = castmask.finditer(self.inhtml)
448                         if castresult:
449                                 Casttext = ""
450                                 for x in castresult:
451                                         Casttext += "\n" + self.htmltags.sub('', x.group(1))
452                                         if x.group(2):
453                                                 Casttext += _(" as ") + self.htmltags.sub('', x.group(2).replace('/ ...',''))
454                                 if Casttext is not "":
455                                         Casttext = _("Cast: ") + Casttext
456                                 else:
457                                         Casttext = _("No cast list found in the database.")
458                                 self["castlabel"].setText(Casttext)
459                         postermask = re.compile('<div class="photo">.*?<img .*? src=\"(http.*?)\" .*?>', re.DOTALL)
460                         posterurl = postermask.search(self.inhtml)
461                         if posterurl and posterurl.group(1).find("jpg") > 0:
462                                 posterurl = posterurl.group(1)
463                                 self["statusbar"].setText(_("Downloading Movie Poster: %s...") % (posterurl))
464                                 localfile = "/tmp/poster.jpg"
465                                 print "[IMDB] downloading poster " + posterurl + " to " + localfile
466                                 downloadPage(posterurl,localfile).addCallback(self.IMDBPoster).addErrback(self.fetchFailed)
467                         else:
468                                 self.IMDBPoster("kein Poster")
469                         extrainfos = self.extrainfomask.search(self.inhtml)
470
471                         if extrainfos:
472                                 Extratext = "Extra Info\n"
473
474                                 for category in ("tagline","outline","synopsis","keywords","awards","runtime","language","color","aspect","sound","cert","locations","company","trivia","goofs","quotes","connections"):
475                                         if extrainfos.group('g_'+category):
476                                                 Extratext += extrainfos.group('g_'+category) + ": " + self.htmltags.sub('',extrainfos.group(category).replace("\n",'').replace("<br>",'\n')) + "\n"
477                                 if extrainfos.group("g_comments"):
478                                         Extratext += extrainfos.group("g_comments") + " [" + self.htmltags.sub('',extrainfos.group("commenter")) + "]: " + self.htmltags.sub('',extrainfos.group("comment").replace("\n",' ')) + "\n"
479
480                                 self["extralabel"].setText(Extratext)
481                                 self["extralabel"].hide()
482                                 self["key_blue"].setText(_("Extra Info"))
483
484                 self["detailslabel"].setText(Detailstext)
485
486         def IMDBPoster(self,string):
487                 self["statusbar"].setText(_("IMDb Details parsed"))
488                 if not string:
489                         filename = "/tmp/poster.jpg"
490                 else:
491                         filename = resolveFilename(SCOPE_PLUGINS, "Extensions/IMDb/no_poster.png")
492                 sc = AVSwitch().getFramebufferScale()
493                 self.picload.setPara((self["poster"].instance.size().width(), self["poster"].instance.size().height(), sc[0], sc[1], False, 1, "#00000000"))
494                 self.picload.startDecode(filename)
495
496         def paintPosterPixmapCB(self, picInfo=None):
497                 ptr = self.picload.getData()
498                 if ptr != None:
499                         self["poster"].instance.setPixmap(ptr.__deref__())
500                         self["poster"].show()
501
502         def createSummary(self):
503                 return IMDbLCDScreen
504
505 class IMDbLCDScreen(Screen):
506         skin = """
507         <screen position="0,0" size="132,64" title="IMDB Plugin">
508                 <widget name="headline" position="4,0" size="128,22" font="Regular;20"/>
509                 <widget source="session.Event_Now" render="Label" position="6,26" size="120,34" font="Regular;14" >
510                         <convert type="EventName">Name</convert>
511                 </widget>
512         </screen>"""
513
514         def __init__(self, session, parent):
515                 Screen.__init__(self, session)
516                 self["headline"] = Label(_("IMDb Plugin"))
517
518 def eventinfo(session, servicelist, **kwargs):
519         ref = session.nav.getCurrentlyPlayingServiceReference()
520         session.open(IMDBEPGSelection, ref)
521
522 def main(session, eventName="", **kwargs):
523         session.open(IMDB, eventName)
524
525 def Plugins(**kwargs):
526         try:
527                 return [PluginDescriptor(name="IMDb Details",
528                                 description=_("Query details from the Internet Movie Database"),
529                                 icon="imdb.png",
530                                 where = PluginDescriptor.WHERE_PLUGINMENU,
531                                 fnc = main),
532                                 PluginDescriptor(name="IMDb Details",
533                                 description=_("Query details from the Internet Movie Database"),
534                                 where = PluginDescriptor.WHERE_EVENTINFO,
535                                 fnc = eventinfo)
536                                 ]
537         except AttributeError:
538                 wherelist = [PluginDescriptor.WHERE_EXTENSIONSMENU, PluginDescriptor.WHERE_PLUGINMENU]
539                 return PluginDescriptor(name="IMDb Details",
540                                 description=_("Query details from the Internet Movie Database"),
541                                 icon="imdb.png",
542                                 where = wherelist,
543                                 fnc=main)