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