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
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"))
30 t = gettext.dgettext("IMDb", txt)
32 print "[IMDb] fallback to default translation for", txt
33 t = gettext.gettext(txt)
37 language.addCallback(localeInit)
39 class IMDBChannelSelection(SimpleChannelSelection):
40 def __init__(self, session):
41 SimpleChannelSelection.__init__(self, session, _("Channel Selection"))
42 self.skinName = "SimpleChannelSelection"
44 self["ChannelSelectEPGActions"] = ActionMap(["ChannelSelectEPGActions"],
46 "showEPGList": self.channelSelected
50 def channelSelected(self):
51 ref = self.getCurrentSelection()
52 if (ref.flags & 7) == 7:
54 elif not (ref.flags & eServiceReference.isMarker):
55 self.session.openWithCallback(
62 def epgClosed(self, ret = None):
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
73 def infoKeyPressed(self):
77 cur = self["list"].getCurrent()
89 self.close(evt.getEventName())
91 def onSelectionChanged(self):
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" />
117 def __init__(self, session, eventName, callbackNeeded=False):
118 Screen.__init__(self, session)
120 self.eventName = eventName
122 self.callbackNeeded = callbackNeeded
123 self.callbackData = ""
124 self.callbackGenre = ""
126 self.dictionary_init()
128 self["poster"] = Pixmap()
129 self.picload = ePicLoad()
130 self.picload.PictureData.get().append(self.paintPosterPixmapCB)
132 self["stars"] = ProgressBar()
133 self["starsbg"] = Pixmap()
135 self["starsbg"].hide()
136 self.ratingstars = -1
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("")
145 self["menu"] = MenuList(self.resultlist)
148 self["key_red"] = Button(_("Exit"))
149 self["key_green"] = Button("")
150 self["key_yellow"] = Button("")
151 self["key_blue"] = Button("")
153 # 0 = multiple query selection menu page
154 # 1 = movie info page
155 # 2 = extra infos page
158 self["actions"] = ActionMap(["OkCancelActions", "ColorActions", "MovieSelectionActions", "DirectionActions"],
160 "ok": self.showDetails,
162 "down": self.pageDown,
165 "green": self.showMenu,
166 "yellow": self.showDetails,
167 "blue": self.showExtras,
168 "contextMenu": self.openChannelSelection,
169 "showEventInfo": self.showDetails
175 if self.callbackNeeded:
176 self.close([self.callbackData, self.callbackGenre])
180 def dictionary_init(self):
181 syslang = language.getLanguage()
182 if "de" not in syslang:
183 self.IMDBlanguage = "" # set to empty ("") for english version
185 self.generalinfomask = re.compile(
186 '<h1 class="header">(?P<title>.*?)<.*?</h1>.*?'
187 '(?:.*?<h4 class="inline">\s*(?P<g_director>Regisseur|Directors?):\s*</h4>.*?<a\s+href=\".*?\">(?P<director>.*?)</a>)*'
188 '(?:.*?<h4 class="inline">\s*(?P<g_creator>Sch\S*?pfer|Creators?):\s*</h4>.*?<a\s+href=\".*?\">(?P<creator>.*?)</a>)*'
189 '(?:.*?<h4 class="inline">\s*(?P<g_seasons>Seasons?):\s*</h4>.*?<a\s+href=\".*?\">(?P<seasons>\d+?)</a>)*'
190 '(?:.*?<h4 class="inline">\s*(?P<g_writer>Drehbuch|Writer).*?</h4>.*?<a\s+href=\".*?\">(?P<writer>.*?)</a>)*'
191 '(?:.*?<h4 class="inline">\s*(?P<g_country>Land|Country):\s*</h4>.*?<a\s+href=\".*?\">(?P<country>.*?)</a>)*'
192 '(?:.*?<h4 class="inline">\s*(?P<g_premiere>Premiere|Release Date).*?</h4>\s+(?P<premiere>.*?)\s*<span)*'
193 '(?:.*?<h4 class="inline">\s*(?P<g_alternativ>Auch bekannt als|Also Known As):\s*</h4>\s*(?P<alternativ>.*?)\s*<span)*'
196 self.extrainfomask = re.compile(
197 '(?:.*?<h4 class="inline">(?P<g_outline>Kurzbeschreibung|Plot Outline):</h4>(?P<outline>.+?)<)*'
198 '(?:.*?<h2>(?P<g_synopsis>Storyline)</h2>.*?<p>(?P<synopsis>.+?)\s*</p>)*'
199 '(?:.*?<h4 class="inline">(?P<g_keywords>Plot Keywords):</h4>(?P<keywords>.+?)(?:Mehr|See more</a>|</div>))*'
200 '(?:.*?<h4 class="inline">(?P<g_tagline>Werbezeile|Tagline?):</h4>\s*(?P<tagline>.+?)<)*'
201 '(?:.*?<h4 class="inline">(?P<g_awards>Filmpreise|Awards):</h4>\s*(?P<awards>.+?)(?:Mehr|See more</a>|</div>))*'
202 '(?:.*?<h4 class="inline">(?P<g_language>Sprache|Language):</h4>\s*(?P<language>.+?)</div>)*'
203 '(?:.*?<h4 class="inline">(?P<g_locations>Drehorte|Filming Locations):</h4>.*?<a\s+href=\".*?\">(?P<locations>.+?)</a>)*'
204 '(?:.*?<h4 class="inline">(?P<g_runtime>L\S*?nge|Runtime):</h4>\s*(?P<runtime>.+?)</div>)*'
205 '(?:.*?<h4 class="inline">(?P<g_sound>Tonverfahren|Sound Mix):</h4>\s*(?P<sound>.+?)</div>)*'
206 '(?:.*?<h4 class="inline">(?P<g_color>Farbe|Color):</h4>\s*(?P<color>.+?)</div>)*'
207 '(?:.*?<h4 class="inline">(?P<g_aspect>Seitenverh\S*?ltnis|Aspect Ratio):</h4>\s*(?P<aspect>.+?)(?:Mehr|See more</a>|</div>))*'
208 '(?:.*?<h4 class="inline">(?P<g_cert>Altersfreigabe|Certification):</h4>\s*(?P<cert>.+?)</div>)*'
209 '(?:.*?<h4 class="inline">(?P<g_company>Firma|Company):</h4>\s*(?P<company>.+?)(?:Mehr|See more</a>|</div>))*'
210 '(?:.*?<h4>(?P<g_trivia>Dies und das|Trivia)</h4>\s*(?P<trivia>.+?)(?:<span))*'
211 '(?:.*?<h4>(?P<g_goofs>Pannen|Goofs)</h4>\s*(?P<goofs>.+?)(?:<span))*'
212 '(?:.*?<h4>(?P<g_quotes>Dialogzitate|Quotes)</h4>\s*(?P<quotes>.+?)(?:<span))*'
213 '(?:.*?<h4>(?P<g_connections>Bez\S*?ge zu anderen Titeln|Movie Connections)</h4>\s*(?P<connections>.+?)(?:<span))*'
214 '(?:.*?<h2>(?P<g_comments>Nutzerkommentare|User Reviews)</h2>.*?<a href="/user/ur\d{7,7}/comments">(?P<commenter>.+?)</a>.*?<p>(?P<comment>.+?)</p>)*'
217 self.genreblockmask = re.compile('<h4 class="inline">Genre:</h4>\s<div class="info-content">\s+?(.*?)\s+?(?:Mehr|See more|</p|<a class|</div>)', re.DOTALL)
218 self.ratingmask = re.compile('<span class="rating-rating">(?P<rating>.*?)<span>/10', re.DOTALL)
219 self.castmask = re.compile('<td class="name">.*?>(.*?)</a>.*?<td class="character">.*?<div>(.*?)</div>', re.DOTALL)
220 self.postermask = re.compile('<td .*?id="img_primary">.*?<img .*?src=\"(http.*?)\"', re.DOTALL)
222 self.IMDBlanguage = "german." # it's a subdomain, so add a '.' at the end
224 self.generalinfomask = re.compile(
225 '<h1>(?P<title>.*?) <.*?</h1>.*?'
226 '(?:.*?<h5>(?P<g_director>Regisseur|Directors?):</h5>.*?<a href=\".*?\">(?P<director>.*?)</a>)*'
227 '(?:.*?<h5>(?P<g_creator>Sch\S*?pfer|Creators?):</h5>.*?<a href=\".*?\">(?P<creator>.*?)</a>)*'
228 '(?:.*?<h5>(?P<g_seasons>Seasons):</h5>(?:.*?)<a href=\".*?\">(?P<seasons>\d+?)</a>\s+?(?:<a class|\|\s+?<a href="episodes#season-unknown))*'
229 '(?:.*?<h5>(?P<g_writer>Drehbuch|Writer).*?</h5>.*?<a href=\".*?\">(?P<writer>.*?)</a>)*'
230 '(?:.*?<h5>(?P<g_premiere>Premiere|Release Date).*?</h5>\s+<div.*?>\s?(?P<premiere>.*?)\n\s.*?<)*'
231 '(?:.*?<h5>(?P<g_alternativ>Auch bekannt als|Also Known As):</h5><div.*?>\s*(?P<alternativ>.*?)(?:<br>)?\s*<a.*?>(?:Mehr|See more))*'
232 '(?:.*?<h5>(?P<g_country>Land|Country):</h5>\s+<div.*?>(?P<country>.*?)</div>(?:.*?Mehr|\s+?</div>))*'
235 self.extrainfomask = re.compile(
236 '(?:.*?<h5>(?P<g_tagline>Werbezeile|Tagline?):</h5>\n(?P<tagline>.+?)<)*'
237 '(?:.*?<h5>(?P<g_outline>Kurzbeschreibung|Plot Outline):</h5>(?P<outline>.+?)<)*'
238 '(?:.*?<h5>(?P<g_synopsis>Plot Synopsis):</h5>(?:.*?)(?:<a href=\".*?\">)*?(?P<synopsis>.+?)(?:</a>|</div>))*'
239 '(?:.*?<h5>(?P<g_keywords>Plot Keywords):</h5>(?P<keywords>.+?)(?:Mehr|See more</a>|</div>))*'
240 '(?:.*?<h5>(?P<g_awards>Filmpreise|Awards):</h5>(?P<awards>.+?)(?:Mehr|See more</a>|</div>))*'
241 '(?:.*?<h5>(?P<g_runtime>L\S*?nge|Runtime):</h5>(?P<runtime>.+?)</div>)*'
242 '(?:.*?<h5>(?P<g_language>Sprache|Language):</h5>(?P<language>.+?)</div>)*'
243 '(?:.*?<h5>(?P<g_color>Farbe|Color):</h5>(?P<color>.+?)</div>)*'
244 '(?:.*?<h5>(?P<g_aspect>Seitenverh\S*?ltnis|Aspect Ratio):</h5>(?P<aspect>.+?)(?:Mehr|See more</a>|</div>))*'
245 '(?:.*?<h5>(?P<g_sound>Tonverfahren|Sound Mix):</h5>(?P<sound>.+?)</div>)*'
246 '(?:.*?<h5>(?P<g_cert>Altersfreigabe|Certification):</h5>(?P<cert>.+?)</div>)*'
247 '(?:.*?<h5>(?P<g_locations>Drehorte|Filming Locations):</h5>(?P<locations>.+?)(?:Mehr|See more</a>|</div>))*'
248 '(?:.*?<h5>(?P<g_company>Firma|Company):</h5>(?P<company>.+?)(?:Mehr|See more</a>|</div>))*'
249 '(?:.*?<h5>(?P<g_trivia>Dies und das|Trivia):</h5>(?P<trivia>.+?)(?:Mehr|See more</a>|</div>))*'
250 '(?:.*?<h5>(?P<g_goofs>Pannen|Goofs):</h5>(?P<goofs>.+?)(?:Mehr|See more</a>|</div>))*'
251 '(?:.*?<h5>(?P<g_quotes>Dialogzitate|Quotes):</h5>(?P<quotes>.+?)(?:Mehr|See more</a>|</div>))*'
252 '(?:.*?<h5>(?P<g_connections>Bez\S*?ge zu anderen Titeln|Movie Connections):</h5>(?P<connections>.+?)(?:Mehr|See more</a>|</div>))*'
253 '(?:.*?<h3>(?P<g_comments>Nutzerkommentare|User Comments)</h3>.*?<a href="/user/ur\d{7,7}/comments">(?P<commenter>.+?)\n</div>.*?<p>(?P<comment>.+?)</p>)*'
256 self.genreblockmask = re.compile('<h5>Genre:</h5>\s<div class="info-content">\s+?(.*?)\s+?(?:Mehr|See more|</p|<a class|</div>)', re.DOTALL)
257 self.ratingmask = re.compile('<h5>(?P<g_rating>Nutzer-Bewertung|User Rating):</h5>.*?<b>(?P<rating>.*?)/10</b>', re.DOTALL)
258 self.castmask = re.compile('<td class="nm">.*?>(.*?)</a>.*?<td class="char">(?:<a.*?>)?(.*?)(?:</a>)?</td>', re.DOTALL)
259 self.postermask = re.compile('<div class="photo">.*?<img .*? src=\"(http.*?)\" .*?>', re.DOTALL)
261 self.htmltags = re.compile('<.*?>')
263 def resetLabels(self):
264 self["detailslabel"].setText("")
265 self["ratinglabel"].setText("")
266 self["titellabel"].setText("")
267 self["castlabel"].setText("")
268 self["titellabel"].setText("")
269 self["extralabel"].setText("")
270 self.ratingstars = -1
274 self["menu"].instance.moveSelection(self["menu"].instance.moveUp)
276 self["castlabel"].pageUp()
277 self["detailslabel"].pageUp()
279 self["extralabel"].pageUp()
283 self["menu"].instance.moveSelection(self["menu"].instance.moveDown)
285 self["castlabel"].pageDown()
286 self["detailslabel"].pageDown()
288 self["extralabel"].pageDown()
291 if ( self.Page is 1 or self.Page is 2 ) and self.resultlist:
294 self["starsbg"].hide()
295 self["ratinglabel"].hide()
296 self["castlabel"].hide()
297 self["poster"].hide()
298 self["extralabel"].hide()
299 self["titellabel"].setText(_("Ambiguous results"))
300 self["detailslabel"].setText(_("Please select the matching entry"))
301 self["detailslabel"].show()
302 self["key_blue"].setText("")
303 self["key_green"].setText(_("Title Menu"))
304 self["key_yellow"].setText(_("Details"))
307 def showDetails(self):
308 self["ratinglabel"].show()
309 self["castlabel"].show()
310 self["detailslabel"].show()
312 if self.resultlist and self.Page == 0:
313 link = self["menu"].getCurrent()[1]
314 title = self["menu"].getCurrent()[0]
315 self["statusbar"].setText(_("Re-Query IMDb: %s...") % (title))
316 localfile = "/tmp/imdbquery2.html"
317 fetchurl = "http://" + self.IMDBlanguage + "imdb.com/title/" + link
318 print "[IMDB] downloading query " + fetchurl + " to " + localfile
319 downloadPage(fetchurl,localfile).addCallback(self.IMDBquery2).addErrback(self.fetchFailed)
325 self["extralabel"].hide()
326 self["poster"].show()
327 if self.ratingstars > 0:
328 self["starsbg"].show()
330 self["stars"].setValue(self.ratingstars)
334 def showExtras(self):
336 self["extralabel"].show()
337 self["detailslabel"].hide()
338 self["castlabel"].hide()
339 self["poster"].hide()
341 self["starsbg"].hide()
342 self["ratinglabel"].hide()
345 def openChannelSelection(self):
346 self.session.openWithCallback(
347 self.channelSelectionClosed,
351 def channelSelectionClosed(self, ret = None):
357 self["ratinglabel"].show()
358 self["castlabel"].show()
359 self["detailslabel"].show()
360 self["poster"].hide()
362 self["starsbg"].hide()
367 if self.eventName is "":
368 s = self.session.nav.getCurrentService()
370 event = info.getEvent(0) # 0 = now, 1 = next
372 self.eventName = event.getEventName()
373 if self.eventName is not "":
374 self["statusbar"].setText(_("Query IMDb: %s...") % (self.eventName))
375 event_quoted = urllib.quote(self.eventName.decode('utf8').encode('latin-1','ignore'))
376 localfile = "/tmp/imdbquery.html"
377 fetchurl = "http://" + self.IMDBlanguage + "imdb.com/find?q=" + event_quoted + "&s=tt&site=aka"
378 print "[IMDB] Downloading Query " + fetchurl + " to " + localfile
379 downloadPage(fetchurl,localfile).addCallback(self.IMDBquery).addErrback(self.fetchFailed)
381 self["statusbar"].setText(_("Could't get Eventname"))
383 def fetchFailed(self,string):
384 print "[IMDB] fetch failed", string
385 self["statusbar"].setText(_("IMDb Download failed"))
387 def html2utf8(self,in_html):
388 htmlentitynumbermask = re.compile('(&#(\d{1,5}?);)')
389 htmlentityhexmask = re.compile('(&#x([0-9A-Fa-f]{2,2}?);)')
390 htmlentitynamemask = re.compile('(&([^#]\D{1,5}?);)')
393 entities = htmlentitynamemask.finditer(in_html)
396 entitydict[x.group(1)] = x.group(2)
397 for key, name in entitydict.items():
398 entitydict[key] = htmlentitydefs.name2codepoint[name]
399 entities = htmlentityhexmask.finditer(in_html)
402 entityhexdict[x.group(1)] = x.group(2)
404 for key, name in entityhexdict.items():
405 entitydict[key] = "%d" % int(key[3:5], 16)
406 print "key:", key, "before:", name, "after:", entitydict[key]
408 entities = htmlentitynumbermask.finditer(in_html)
410 entitydict[x.group(1)] = x.group(2)
411 for key, codepoint in entitydict.items():
412 in_html = in_html.replace(key, (unichr(int(codepoint)).encode('latin-1', 'ignore')))
413 self.inhtml = in_html.decode('latin-1').encode('utf8')
415 def IMDBquery(self,string):
417 self["statusbar"].setText(_("IMDb Download completed"))
419 self.html2utf8(open("/tmp/imdbquery.html", "r").read())
421 self.generalinfos = self.generalinfomask.search(self.inhtml)
423 if self.generalinfos:
426 if re.search("<title>(?:IMDb.{0,9}Search|IMDb Titelsuche)</title>", self.inhtml):
427 searchresultmask = re.compile("<tr> <td.*?img src.*?>.*?<a href=\".*?/title/(tt\d{7,7})/\".*?>(.*?)</td>", re.DOTALL)
428 searchresults = searchresultmask.finditer(self.inhtml)
429 self.resultlist = [(self.htmltags.sub('',x.group(2)), x.group(1)) for x in searchresults]
430 self["menu"].l.setList(self.resultlist)
431 if len(self.resultlist) > 1:
435 self["detailslabel"].setText(_("No IMDb match."))
436 self["statusbar"].setText(_("No IMDb match."))
438 splitpos = self.eventName.find('(')
439 if splitpos > 0 and self.eventName.endswith(')'):
440 self.eventName = self.eventName[splitpos+1:-1]
441 self["statusbar"].setText(_("Re-Query IMDb: %s...") % (self.eventName))
442 event_quoted = urllib.quote(self.eventName.decode('utf8').encode('latin-1','ignore'))
443 localfile = "/tmp/imdbquery.html"
444 fetchurl = "http://" + self.IMDBlanguage + "imdb.com/find?q=" + event_quoted + "&s=tt&site=aka"
445 print "[IMDB] Downloading Query " + fetchurl + " to " + localfile
446 downloadPage(fetchurl,localfile).addCallback(self.IMDBquery).addErrback(self.fetchFailed)
448 self["detailslabel"].setText(_("IMDb query failed!"))
450 def IMDBquery2(self,string):
451 self["statusbar"].setText(_("IMDb Re-Download completed"))
452 self.html2utf8(open("/tmp/imdbquery2.html", "r").read())
453 self.generalinfos = self.generalinfomask.search(self.inhtml)
459 Detailstext = _("No details found.")
460 if self.generalinfos:
461 self["key_yellow"].setText(_("Details"))
462 self["statusbar"].setText(_("IMDb Details parsed"))
463 Titeltext = self.generalinfos.group("title")
464 if len(Titeltext) > 57:
465 Titeltext = Titeltext[0:54] + "..."
466 self["titellabel"].setText(Titeltext)
470 genreblock = self.genreblockmask.findall(self.inhtml)
472 genres = self.htmltags.sub('', genreblock[0])
474 Detailstext += "Genre: "
475 Detailstext += genres
476 self.callbackGenre = genres
478 for category in ("director", "creator", "writer", "seasons"):
479 if self.generalinfos.group(category):
480 Detailstext += "\n" + self.generalinfos.group('g_'+category) + ": " + self.generalinfos.group(category)
482 for category in ("premiere", "country", "alternativ"):
483 if self.generalinfos.group(category):
484 Detailstext += "\n" + self.generalinfos.group('g_'+category) + ": " + self.htmltags.sub('', self.generalinfos.group(category).replace('\n',' ').replace("<br>", '\n').replace("<br />",'\n').replace(" ",' '))
486 rating = self.ratingmask.search(self.inhtml)
487 Ratingtext = _("no user rating yet")
489 rating = rating.group("rating")
491 Ratingtext = _("User Rating") + ": " + rating + " / 10"
492 self.ratingstars = int(10*round(float(rating.replace(',','.')),1))
494 self["stars"].setValue(self.ratingstars)
495 self["starsbg"].show()
496 self["ratinglabel"].setText(Ratingtext)
498 castresult = self.castmask.finditer(self.inhtml)
502 Casttext += "\n" + self.htmltags.sub('', x.group(1))
504 Casttext += _(" as ") + self.htmltags.sub('', x.group(2).replace('/ ...','')).replace('\n', ' ').replace(" ", ' ').strip()
505 if Casttext is not "":
506 Casttext = _("Cast: ") + Casttext
508 Casttext = _("No cast list found in the database.")
509 self["castlabel"].setText(Casttext)
511 posterurl = self.postermask.search(self.inhtml)
512 if posterurl and posterurl.group(1).find("jpg") > 0:
513 posterurl = posterurl.group(1)
514 self["statusbar"].setText(_("Downloading Movie Poster: %s...") % (posterurl))
515 localfile = "/tmp/poster.jpg"
516 print "[IMDB] downloading poster " + posterurl + " to " + localfile
517 downloadPage(posterurl,localfile).addCallback(self.IMDBPoster).addErrback(self.fetchFailed)
519 self.IMDBPoster("kein Poster")
520 extrainfos = self.extrainfomask.search(self.inhtml)
523 Extratext = "Extra Info\n"
525 for category in ("tagline","outline","synopsis","keywords","awards","runtime","language","color","aspect","sound","cert","locations","company","trivia","goofs","quotes","connections"):
526 if extrainfos.group('g_'+category):
527 Extratext += extrainfos.group('g_'+category) + ": " + self.htmltags.sub('',extrainfos.group(category).replace("\n",'').replace("<br>", '\n').replace("<br />",'\n')) + "\n"
528 if extrainfos.group("g_comments"):
529 stripmask = re.compile('\s{2,}', re.DOTALL)
530 Extratext += extrainfos.group("g_comments") + " [" + stripmask.sub(' ', self.htmltags.sub('',extrainfos.group("commenter"))) + "]: " + self.htmltags.sub('',extrainfos.group("comment").replace("\n",' ')) + "\n"
532 self["extralabel"].setText(Extratext)
533 self["extralabel"].hide()
534 self["key_blue"].setText(_("Extra Info"))
536 self["detailslabel"].setText(Detailstext)
537 self.callbackData = Detailstext
539 def IMDBPoster(self,string):
540 self["statusbar"].setText(_("IMDb Details parsed"))
542 filename = "/tmp/poster.jpg"
544 filename = resolveFilename(SCOPE_PLUGINS, "Extensions/IMDb/no_poster.png")
545 sc = AVSwitch().getFramebufferScale()
546 self.picload.setPara((self["poster"].instance.size().width(), self["poster"].instance.size().height(), sc[0], sc[1], False, 1, "#00000000"))
547 self.picload.startDecode(filename)
549 def paintPosterPixmapCB(self, picInfo=None):
550 ptr = self.picload.getData()
552 self["poster"].instance.setPixmap(ptr.__deref__())
553 self["poster"].show()
555 def createSummary(self):
558 class IMDbLCDScreen(Screen):
560 <screen position="0,0" size="132,64" title="IMDB Plugin">
561 <widget name="headline" position="4,0" size="128,22" font="Regular;20"/>
562 <widget source="session.Event_Now" render="Label" position="6,26" size="120,34" font="Regular;14" >
563 <convert type="EventName">Name</convert>
567 def __init__(self, session, parent):
568 Screen.__init__(self, session)
569 self["headline"] = Label(_("IMDb Plugin"))
571 def eventinfo(session, servicelist, **kwargs):
572 ref = session.nav.getCurrentlyPlayingServiceReference()
573 session.open(IMDBEPGSelection, ref)
575 def main(session, eventName="", **kwargs):
576 session.open(IMDB, eventName)
578 def Plugins(**kwargs):
580 return [PluginDescriptor(name="IMDb Details",
581 description=_("Query details from the Internet Movie Database"),
583 where = PluginDescriptor.WHERE_PLUGINMENU,
585 PluginDescriptor(name="IMDb Details",
586 description=_("Query details from the Internet Movie Database"),
587 where = PluginDescriptor.WHERE_EVENTINFO,
590 except AttributeError:
591 wherelist = [PluginDescriptor.WHERE_EXTENSIONSMENU, PluginDescriptor.WHERE_PLUGINMENU]
592 return PluginDescriptor(name="IMDb Details",
593 description=_("Query details from the Internet Movie Database"),