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 style="display:none" id="star-bar-user-rate"><b>(?P<rating>.*?)</b>', re.DOTALL)
219 self.castmask = re.compile('<td class="name">\s*<a.*?>(.*?)</a>.*?<td class="character">\s*<div>\s*(?:<a.*?>)?(.*?)(?:</a>)?\s*( \(as.*?\))?\s*</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>)?(\s\(.*?\))?</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):
390 entities = re.finditer('&([^#]\D{1,5}?);', in_html)
393 if key not in entitydict:
394 entitydict[key] = htmlentitydefs.name2codepoint[x.group(1)]
396 entities = re.finditer('&#x([0-9A-Fa-f]{2,2}?);', in_html)
399 if key not in entitydict:
400 entitydict[key] = "%d" % int(key[3:5], 16)
402 entities = re.finditer('&#(\d{1,5}?);', in_html)
405 if key not in entitydict:
406 entitydict[key] = x.group(1)
408 for key, codepoint in entitydict.items():
409 in_html = in_html.replace(key, unichr(int(codepoint)).encode('latin-1', 'ignore'))
410 self.inhtml = in_html.decode('latin-1').encode('utf8')
412 def IMDBquery(self,string):
414 self["statusbar"].setText(_("IMDb Download completed"))
416 self.html2utf8(open("/tmp/imdbquery.html", "r").read())
418 self.generalinfos = self.generalinfomask.search(self.inhtml)
420 if self.generalinfos:
423 if re.search("<title>(?:IMDb.{0,9}Search|IMDb Titelsuche)</title>", self.inhtml):
424 searchresultmask = re.compile("<tr> <td.*?img src.*?>.*?<a href=\".*?/title/(tt\d{7,7})/\".*?>(.*?)</td>", re.DOTALL)
425 searchresults = searchresultmask.finditer(self.inhtml)
426 self.resultlist = [(self.htmltags.sub('',x.group(2)), x.group(1)) for x in searchresults]
427 self["menu"].l.setList(self.resultlist)
428 if len(self.resultlist) > 1:
432 self["detailslabel"].setText(_("No IMDb match."))
433 self["statusbar"].setText(_("No IMDb match."))
435 splitpos = self.eventName.find('(')
436 if splitpos > 0 and self.eventName.endswith(')'):
437 self.eventName = self.eventName[splitpos+1:-1]
438 self["statusbar"].setText(_("Re-Query IMDb: %s...") % (self.eventName))
439 event_quoted = urllib.quote(self.eventName.decode('utf8').encode('latin-1','ignore'))
440 localfile = "/tmp/imdbquery.html"
441 fetchurl = "http://" + self.IMDBlanguage + "imdb.com/find?q=" + event_quoted + "&s=tt&site=aka"
442 print "[IMDB] Downloading Query " + fetchurl + " to " + localfile
443 downloadPage(fetchurl,localfile).addCallback(self.IMDBquery).addErrback(self.fetchFailed)
445 self["detailslabel"].setText(_("IMDb query failed!"))
447 def IMDBquery2(self,string):
448 self["statusbar"].setText(_("IMDb Re-Download completed"))
449 self.html2utf8(open("/tmp/imdbquery2.html", "r").read())
450 self.generalinfos = self.generalinfomask.search(self.inhtml)
456 Detailstext = _("No details found.")
457 if self.generalinfos:
458 self["key_yellow"].setText(_("Details"))
459 self["statusbar"].setText(_("IMDb Details parsed"))
460 Titeltext = self.generalinfos.group("title")
461 if len(Titeltext) > 57:
462 Titeltext = Titeltext[0:54] + "..."
463 self["titellabel"].setText(Titeltext)
467 genreblock = self.genreblockmask.findall(self.inhtml)
469 genres = self.htmltags.sub('', genreblock[0])
471 Detailstext += "Genre: "
472 Detailstext += genres
473 self.callbackGenre = genres
475 for category in ("director", "creator", "writer", "seasons"):
476 if self.generalinfos.group(category):
477 Detailstext += "\n" + self.generalinfos.group('g_'+category) + ": " + self.generalinfos.group(category)
479 for category in ("premiere", "country", "alternativ"):
480 if self.generalinfos.group(category):
481 Detailstext += "\n" + self.generalinfos.group('g_'+category) + ": " + self.htmltags.sub('', self.generalinfos.group(category).replace('\n',' ').replace("<br>", '\n').replace("<br />",'\n').replace(" ",' '))
483 rating = self.ratingmask.search(self.inhtml)
484 Ratingtext = _("no user rating yet")
486 rating = rating.group("rating")
487 if rating != '<span id="voteuser"></span>':
488 Ratingtext = _("User Rating") + ": " + rating + " / 10"
489 self.ratingstars = int(10*round(float(rating.replace(',','.')),1))
491 self["stars"].setValue(self.ratingstars)
492 self["starsbg"].show()
493 self["ratinglabel"].setText(Ratingtext)
495 castresult = self.castmask.finditer(self.inhtml)
499 Casttext += "\n" + self.htmltags.sub('', x.group(1))
501 Casttext += _(" as ") + self.htmltags.sub('', x.group(2).replace('/ ...','')).replace('\n', ' ')
503 Casttext += x.group(3)
504 if Casttext is not "":
505 Casttext = _("Cast: ") + Casttext
507 Casttext = _("No cast list found in the database.")
508 self["castlabel"].setText(Casttext)
510 posterurl = self.postermask.search(self.inhtml)
511 if posterurl and posterurl.group(1).find("jpg") > 0:
512 posterurl = posterurl.group(1)
513 self["statusbar"].setText(_("Downloading Movie Poster: %s...") % (posterurl))
514 localfile = "/tmp/poster.jpg"
515 print "[IMDB] downloading poster " + posterurl + " to " + localfile
516 downloadPage(posterurl,localfile).addCallback(self.IMDBPoster).addErrback(self.fetchFailed)
518 self.IMDBPoster("kein Poster")
519 extrainfos = self.extrainfomask.search(self.inhtml)
522 Extratext = "Extra Info\n"
524 for category in ("tagline","outline","synopsis","keywords","awards","runtime","language","color","aspect","sound","cert","locations","company","trivia","goofs","quotes","connections"):
525 if extrainfos.group('g_'+category):
526 Extratext += extrainfos.group('g_'+category) + ": " + self.htmltags.sub('',extrainfos.group(category).replace("\n",'').replace("<br>", '\n').replace("<br />",'\n')) + "\n"
527 if extrainfos.group("g_comments"):
528 stripmask = re.compile('\s{2,}', re.DOTALL)
529 Extratext += extrainfos.group("g_comments") + " [" + stripmask.sub(' ', self.htmltags.sub('',extrainfos.group("commenter"))) + "]: " + self.htmltags.sub('',extrainfos.group("comment").replace("\n",' ')) + "\n"
531 self["extralabel"].setText(Extratext)
532 self["extralabel"].hide()
533 self["key_blue"].setText(_("Extra Info"))
535 self["detailslabel"].setText(Detailstext)
536 self.callbackData = Detailstext
538 def IMDBPoster(self,string):
539 self["statusbar"].setText(_("IMDb Details parsed"))
541 filename = "/tmp/poster.jpg"
543 filename = resolveFilename(SCOPE_PLUGINS, "Extensions/IMDb/no_poster.png")
544 sc = AVSwitch().getFramebufferScale()
545 self.picload.setPara((self["poster"].instance.size().width(), self["poster"].instance.size().height(), sc[0], sc[1], False, 1, "#00000000"))
546 self.picload.startDecode(filename)
548 def paintPosterPixmapCB(self, picInfo=None):
549 ptr = self.picload.getData()
551 self["poster"].instance.setPixmap(ptr.__deref__())
552 self["poster"].show()
554 def createSummary(self):
557 class IMDbLCDScreen(Screen):
559 <screen position="0,0" size="132,64" title="IMDB Plugin">
560 <widget name="headline" position="4,0" size="128,22" font="Regular;20"/>
561 <widget source="session.Event_Now" render="Label" position="6,26" size="120,34" font="Regular;14" >
562 <convert type="EventName">Name</convert>
566 def __init__(self, session, parent):
567 Screen.__init__(self, session)
568 self["headline"] = Label(_("IMDb Plugin"))
570 def eventinfo(session, servicelist, **kwargs):
571 ref = session.nav.getCurrentlyPlayingServiceReference()
572 session.open(IMDBEPGSelection, ref)
574 def main(session, eventName="", **kwargs):
575 session.open(IMDB, eventName)
577 def Plugins(**kwargs):
579 return [PluginDescriptor(name="IMDb Details",
580 description=_("Query details from the Internet Movie Database"),
582 where = PluginDescriptor.WHERE_PLUGINMENU,
584 PluginDescriptor(name="IMDb Details",
585 description=_("Query details from the Internet Movie Database"),
586 where = PluginDescriptor.WHERE_EVENTINFO,
589 except AttributeError:
590 wherelist = [PluginDescriptor.WHERE_EXTENSIONSMENU, PluginDescriptor.WHERE_PLUGINMENU]
591 return PluginDescriptor(name="IMDb Details",
592 description=_("Query details from the Internet Movie Database"),