movielistpreview: ignore ePicLoad's picInfo
[enigma2-plugins.git] / movielistpreview / src / plugin.py
1 ##
2 ## Movielist Preview
3 ## by AliAbdul
4 ##
5 from Components.ActionMap import ActionMap
6 from Components.AVSwitch import AVSwitch
7 from Components.config import config, ConfigInteger, ConfigSelection, ConfigSubsection, ConfigYesNo, getConfigListEntry\r
8 from Components.ConfigList import ConfigListScreen
9 from Components.Console import Console
10 from Components.Label import Label
11 from Components.Language import language
12 from Components.MenuList import MenuList
13 from Components.MovieList import MovieList
14 from Components.Pixmap import Pixmap
15 from Components.ServiceEventTracker import InfoBarBase
16 from Components.VideoWindow import VideoWindow
17 from enigma import ePicLoad, ePoint, eServiceReference, eSize, eTimer, getDesktop
18 from os import environ, listdir
19 from Plugins.Plugin import PluginDescriptor
20 from Screens.InfoBarGenerics import InfoBarSeek, InfoBarCueSheetSupport
21 from Screens.MessageBox import MessageBox
22 from Screens.MovieSelection import MovieSelection
23 from Screens.Screen import Screen
24 from Tools.Directories import fileExists, resolveFilename, SCOPE_LANGUAGE, SCOPE_PLUGINS
25 import gettext, random
26
27 ##############################################################################
28
29 config.plugins.MovielistPreview = ConfigSubsection()
30 config.plugins.MovielistPreview.enabled = ConfigYesNo(default=True)
31 config.plugins.MovielistPreview.position_x = ConfigInteger(default=100)
32 config.plugins.MovielistPreview.position_y = ConfigInteger(default=100)
33 config.plugins.MovielistPreview.size = ConfigSelection(choices=["250x200", "200x160", "150x120", "100x80"], default="250x200")
34
35 ##############################################################################
36
37 def localeInit():
38         lang = language.getLanguage()
39         environ["LANGUAGE"] = lang[:2]
40         gettext.bindtextdomain("enigma2", resolveFilename(SCOPE_LANGUAGE))
41         gettext.textdomain("enigma2")
42         gettext.bindtextdomain("MovielistPreview", "%s%s" % (resolveFilename(SCOPE_PLUGINS), "Extensions/MovielistPreview/locale/"))
43
44 def _(txt):
45         t = gettext.dgettext("MovielistPreview", txt)
46         if t == txt:
47                 t = gettext.gettext(txt)
48         return t
49
50 localeInit()
51 language.addCallback(localeInit)
52
53 ##############################################################################
54
55 SKIN = """
56         <screen position="0,0" size="250,200" zPosition="10" flags="wfNoBorder" backgroundColor="#FF000000" >
57                 <widget name="background" position="0,0" size="250,200" zPosition="1" backgroundColor="#00000000" />
58                 <widget name="preview" position="0,0" size="250,200" zPosition="2" />
59         </screen>"""
60
61 ##############################################################################
62
63 class MovielistPreviewScreen(Screen):
64         def __init__(self, session):
65                 Screen.__init__(self, session)
66                 self.skin = SKIN
67                 self["background"] = Label("")
68                 self["preview"] = Pixmap()
69                 self.onShow.append(self.movePosition)
70
71         def movePosition(self):
72                 if self.instance:
73                         self.instance.move(ePoint(config.plugins.MovielistPreview.position_x.value, config.plugins.MovielistPreview.position_y.value))
74                         size = config.plugins.MovielistPreview.size.value.split("x")
75                         self.instance.resize(eSize(int(size[0]), int(size[1])))
76                         self["background"].instance.resize(eSize(int(size[0]), int(size[1])))
77                         self["preview"].instance.resize(eSize(int(size[0]), int(size[1])))
78
79 ##############################################################################
80
81 class MovielistPreview():
82         def __init__(self):
83                 self.dialog = None
84                 self.mayShow = True
85                 self.working = False
86
87         def gotSession(self, session):
88                 if not self.dialog:
89                         self.dialog = session.instantiateDialog(MovielistPreviewScreen)
90
91         def changeVisibility(self):
92                 if config.plugins.MovielistPreview.enabled.value:
93                         config.plugins.MovielistPreview.enabled.value = False
94                 else:
95                         config.plugins.MovielistPreview.enabled.value = True
96                 config.plugins.MovielistPreview.enabled.save()
97
98         def showPreview(self, movie):
99                 if self.working == False:
100                         self.dialog.hide()
101                         if movie and self.mayShow and config.plugins.MovielistPreview.enabled.value:
102                                 png = movie + "_mp.jpg"
103                                 if fileExists(png):
104                                         self.working = True
105                                         sc = AVSwitch().getFramebufferScale()
106                                         self.picload = ePicLoad()
107                                         self.picload.PictureData.get().append(self.showPreviewCallback)
108                                         size = config.plugins.MovielistPreview.size.value.split("x")
109                                         self.picload.setPara((int(size[0]), int(size[1]), sc[0], sc[1], False, 1, "#00000000"))
110                                         self.picload.startDecode(png)
111
112         def showPreviewCallback(self, picInfo=None):
113                 ptr = self.picload.getData()
114                 if ptr != None:
115                         self.dialog["preview"].instance.setPixmap(ptr)
116                         self.dialog.show()
117                 self.working = False
118
119         def hideDialog(self):
120                 self.mayShow = False
121                 self.dialog.hide()
122
123         def showDialog(self):
124                 self.mayShow = True
125                 self.dialog.show()
126 movielistpreview = MovielistPreview()
127
128 ##############################################################################
129
130 class MovielistPreviewPositionerCoordinateEdit(ConfigListScreen, Screen):\r
131         skin = """\r
132                 <screen position="center,center" size="560,110" title="%s">\r
133                         <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" transparent="1" alphatest="on" />\r
134                         <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" transparent="1" alphatest="on" />\r
135                         <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" size="140,40" transparent="1" alphatest="on" />\r
136                         <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" size="140,40" transparent="1" alphatest="on" />\r
137                         <widget name="key_green" position="140,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" />\r
138                         <widget name="config" position="0,45" size="560,60" scrollbarMode="showOnDemand" />\r
139                 </screen>""" % _("Movielist Preview")
140
141         def __init__(self, session, x, y, w, h):\r
142                 Screen.__init__(self, session)
143                 \r
144                 self["key_green"] = Label(_("OK"))
145                 
146                 self.xEntry = ConfigInteger(default=x, limits=(0, w))
147                 self.yEntry = ConfigInteger(default=y, limits=(0, h))\r
148                 ConfigListScreen.__init__(self, [
149                         getConfigListEntry("x position:", self.xEntry),
150                         getConfigListEntry("y position:", self.yEntry)])
151                 \r
152                 self["actions"] = ActionMap(["OkCancelActions", "ColorActions"],
153                         {
154                                 "green": self.ok,
155                                  "cancel": self.close
156                         }, -1)
157
158         def ok(self):
159                 self.close([self.xEntry.value, self.yEntry.value])
160
161 ##############################################################################
162
163 class MovielistPreviewPositioner(Screen):
164         def __init__(self, session):
165                 Screen.__init__(self, session)
166                 self.skin = SKIN
167                 self["background"] = Label("")
168                 self["preview"] = Pixmap()
169                 
170                 self["actions"] = ActionMap(["EPGSelectActions", "MenuActions", "WizardActions"],
171                 {
172                         "left": self.left,
173                         "up": self.up,
174                         "right": self.right,
175                         "down": self.down,
176                         "ok": self.ok,
177                         "back": self.exit,
178                         "menu": self.editCoordinates,
179                         "nextBouquet": self.bigger,
180                         "prevBouquet": self.smaller
181                 }, -1)
182                 
183                 desktop = getDesktop(0)
184                 self.desktopWidth = desktop.size().width()
185                 self.desktopHeight = desktop.size().height()
186                 
187                 self.moveTimer = eTimer()
188                 self.moveTimer.callback.append(self.movePosition)
189                 self.moveTimer.start(50, 1)
190                 
191                 self.onShow.append(self.__onShow)
192
193         def __onShow(self):
194                 if self.instance:
195                         size = config.plugins.MovielistPreview.size.value.split("x")
196                         self.instance.resize(eSize(int(size[0]), int(size[1])))
197                         self["background"].instance.resize(eSize(int(size[0]), int(size[1])))
198                         self["preview"].instance.resize(eSize(int(size[0]), int(size[1])))
199
200         def movePosition(self):
201                 self.instance.move(ePoint(config.plugins.MovielistPreview.position_x.value, config.plugins.MovielistPreview.position_y.value))
202                 self.moveTimer.start(50, 1)
203
204         def left(self):
205                 value = config.plugins.MovielistPreview.position_x.value
206                 value -= 1
207                 if value < 0:
208                         value = 0
209                 config.plugins.MovielistPreview.position_x.value = value
210
211         def up(self):
212                 value = config.plugins.MovielistPreview.position_y.value
213                 value -= 1
214                 if value < 0:
215                         value = 0
216                 config.plugins.MovielistPreview.position_y.value = value
217
218         def right(self):
219                 value = config.plugins.MovielistPreview.position_x.value
220                 value += 1
221                 if value > self.desktopWidth:
222                         value = self.desktopWidth
223                 config.plugins.MovielistPreview.position_x.value = value
224
225         def down(self):
226                 value = config.plugins.MovielistPreview.position_y.value
227                 value += 1
228                 if value > self.desktopHeight:
229                         value = self.desktopHeight
230                 config.plugins.MovielistPreview.position_y.value = value
231
232         def ok(self):
233                 config.plugins.MovielistPreview.position_x.save()
234                 config.plugins.MovielistPreview.position_y.save()
235                 self.close()
236
237         def exit(self):
238                 config.plugins.MovielistPreview.position_x.cancel()
239                 config.plugins.MovielistPreview.position_y.cancel()
240                 self.close()
241
242         def editCoordinates(self):
243                 self.session.openWithCallback(self.editCoordinatesCallback, MovielistPreviewPositionerCoordinateEdit, config.plugins.MovielistPreview.position_x.value, config.plugins.MovielistPreview.position_y.value, self.desktopWidth, self.desktopHeight)
244
245         def editCoordinatesCallback(self, callback=None):
246                 if callback:
247                         config.plugins.MovielistPreview.position_x.value = callback[0]
248                         config.plugins.MovielistPreview.position_y.value = callback[1]
249
250         def bigger(self):
251                 if config.plugins.MovielistPreview.size.value == "200x160":
252                         config.plugins.MovielistPreview.size.value = "250x200"
253                 elif config.plugins.MovielistPreview.size.value == "150x120":
254                         config.plugins.MovielistPreview.size.value = "200x160"
255                 elif config.plugins.MovielistPreview.size.value == "100x80":
256                         config.plugins.MovielistPreview.size.value = "150x120"
257                 config.plugins.MovielistPreview.size.save()
258                 self.__onShow()
259
260         def smaller(self):
261                 if config.plugins.MovielistPreview.size.value == "150x120":
262                         config.plugins.MovielistPreview.size.value = "100x80"
263                 elif config.plugins.MovielistPreview.size.value == "200x160":
264                         config.plugins.MovielistPreview.size.value = "150x120"
265                 elif config.plugins.MovielistPreview.size.value == "250x200":
266                         config.plugins.MovielistPreview.size.value = "200x160"
267                 config.plugins.MovielistPreview.size.save()
268                 self.__onShow()
269
270 ##############################################################################
271
272 class PreviewCreator:
273         def __init__(self):
274                 self.callback = None
275                 self.Console = Console()
276
277         def grab(self, file):
278                 if not self.Console:
279                         self.Console = Console()
280                 self.Console.ePopen('/usr/bin/grab -v -r 250 -l -j 100 "%s"'%file, self.grabDone)
281
282         def grabDone(self, result, retval, extra_args):
283                 if retval != 0:
284                         print result
285                 if self.callback:
286                         self.callback()
287 previewcreator = PreviewCreator()
288
289 ##############################################################################
290
291 class MovielistPreviewManualCreator(Screen, InfoBarBase, InfoBarSeek, InfoBarCueSheetSupport):
292         skin = """
293                 <screen position="center,center" size="560,380" title="%s">
294                         <widget name="video" position="100,20" size="360,288" backgroundColor="transparent" />
295                         <widget source="session.CurrentService" render="PositionGauge" position="145,330" size="270,10" pointer="skin_default/position_pointer.png:540,0" transparent="1" foregroundColor="#20224f">
296                                 <convert type="ServicePosition">Gauge</convert>
297                         </widget>
298                         <widget name="seekState" position="40,320" size="60,25" halign="right" font="Regular;18" valign="center" />
299                         <ePixmap pixmap="skin_default/icons/mp_buttons.png" position="225,350" size="109,13" alphatest="on" />
300                 </screen>""" % _("Movielist Preview")
301
302         def __init__(self, session, service):
303                 Screen.__init__(self, session)
304                 InfoBarSeek.__init__(self)
305                 InfoBarCueSheetSupport.__init__(self)
306                 InfoBarBase.__init__(self, steal_current_service=True)
307                 
308                 self.session = session
309                 self.service = service
310                 self.working = False
311                 self.oldService = self.session.nav.getCurrentlyPlayingServiceReference()
312                 self.session.nav.playService(service)
313                 previewcreator.callback = self.grabDone
314                 
315                 desktopSize = getDesktop(0).size()
316                 self["video"] = VideoWindow(decoder=0, fb_width=desktopSize.width(), fb_height=desktopSize.height())
317                 self["seekState"] = Label()
318                 
319                 self.onPlayStateChanged.append(self.updateStateLabel)
320                 self.updateStateLabel(self.seekstate)
321                 
322                 self["actions"] = ActionMap(["OkCancelActions"],
323                         {
324                                 "ok": self.grab,
325                                 "cancel": self.exit
326                         }, -2)
327
328         def checkSkipShowHideLock(self):
329                 pass
330
331         def updateStateLabel(self, state):
332                 self["seekState"].setText(state[3].strip())
333
334         def grab(self):
335                 if not self.working:
336                         self.working = True
337                         png = self.service.getPath() + "_mp.jpg"
338                         previewcreator.grab(png)
339
340         def grabDone(self):
341                 self.working = False
342                 self.session.open(MessageBox,_("Preview created."), MessageBox.TYPE_INFO, timeout=5)
343
344         def exit(self):
345                 if not self.working:
346                         self.session.nav.playService(self.oldService)
347                         self.close()
348
349 ##############################################################################
350
351 class MovielistPreviewAutoCreator(Screen):
352         skin = """
353                 <screen position="center,center" size="420,105" title="%s">
354                         <widget name="label" position="10,10" size="400,85" transparent="1" font="Regular;20" halign="center" valign="center" />
355                 </screen>""" % _("Movielist Preview")
356
357         def __init__(self, session):
358                 Screen.__init__(self, session)
359                 
360                 self.session = session
361                 self.files = []
362                 self.filescount = 0
363                 self.current = 1
364                 self.working = True
365                 self.abort = False
366                 self.dir = config.movielist.last_videodir.value
367                 previewcreator.callback = self.grabDone
368                 self.playable = ["avi", "dat", "divx", "m2ts", "m4a", "mkv", "mp4", "mov", "mpg", "ts", "vob"]
369                 self.oldService = self.session.nav.getCurrentlyPlayingServiceReference()
370                 
371                 self["label"] = Label()
372                 
373                 self.timer = eTimer()
374                 self.timer.callback.append(self.seekAndCreatePreview)
375                 
376                 self["actions"] = ActionMap(["OkCancelActions"], {"cancel": self.exit}, -1)
377                 
378                 self.onLayoutFinish.append(self.createPreviews)
379
380         def exit(self):
381                 if self.working == False:
382                         self.session.nav.playService(self.oldService)
383                         self.close()
384                 else:
385                         self.abort = True
386
387         def getExtension(self, name):
388                 ext = None
389                 if name.__contains__("."):
390                         tmp = name.split(".")
391                         ext = tmp[-1]
392                 return ext
393
394         def createPreviews(self):
395                 try:
396                         files = listdir(self.dir)
397                 except:
398                         files = []
399                 for file in files:
400                         ext = self.getExtension(file)
401                         if ext and (ext.lower() in self.playable):
402                                 self.files.append(file)
403                 self.filescount = len(self.files)
404                 if self.filescount == 0:
405                         self["label"].setText(_("Could not find any movie!"))
406                 else:
407                         self.createNextPreview()
408
409         def createNextPreview(self):
410                 if len(self.files):
411                         file = self.files[0]
412                         movie = ("%s/%s" % (self.dir, file)).replace("//", "/")
413                         png = movie + "_mp.jpg"
414                         if fileExists(png):
415                                 self.grabDone()
416                         else:
417                                 counter = "%d / %d" % (self.current, self.filescount)
418                                 self["label"].setText(_("%s - creating preview for movie %s") % (counter, movie))
419                                 if movie.endswith(".ts"):
420                                         ref = eServiceReference(1, 0, movie)
421                                 else:
422                                         ref = eServiceReference(4097, 0, movie)
423                                 self.session.nav.playService(ref)
424                                 self.png = png
425                                 self.timer.start(5000, 1)
426                 else:
427                         self["label"].setText(_("Everything done ;)"))
428                         self.working = False
429
430         def seekAndCreatePreview(self):
431                 service = self.session.nav.getCurrentService()
432                 if service:
433                         cue = service and service.cueSheet()
434                         if cue is not None:
435                                 cue.setCutListEnable(0)
436                         seek = service.seek()
437                         if seek:
438                                 length = int(seek.getLength()[1])
439                                 seek.seekTo(random.randint(0, length))
440                         previewcreator.grab(self.png)
441                 else:
442                         self.grabDone()
443
444         def grabDone(self):
445                 del self.files[0]
446                 self.current += 1
447                 if self.abort:
448                         self["label"].setText(_("Autocreate of previews aborted due user!"))
449                         self.working = False
450                 else:
451                         self.createNextPreview()
452
453 ##############################################################################
454
455 class MovielistPreviewMenu(Screen):
456         skin = """
457                 <screen position="center,center" size="420,105" title="%s">
458                         <widget name="list" position="5,5" size="410,100" />
459                 </screen>""" % _("Movielist Preview")
460
461         def __init__(self, session, service):
462                 Screen.__init__(self, session)
463                 self.session = session
464                 self.service = service
465                 self["list"] = MenuList([])
466                 self["actions"] = ActionMap(["OkCancelActions"], {"ok": self.okClicked, "cancel": self.close}, -1)
467                 self.onLayoutFinish.append(self.showMenu)
468
469         def showMenu(self):
470                 list = []
471                 if config.plugins.MovielistPreview.enabled.value:
472                         list.append(_("Deactivate Movielist Preview"))
473                 else:
474                         list.append(_("Activate Movielist Preview"))
475                 list.append(_("Create preview"))
476                 list.append(_("Autocreate of missing previews"))
477                 list.append(_("Change Movielist Preview position"))
478                 self["list"].setList(list)
479
480         def okClicked(self):
481                 idx = self["list"].getSelectionIndex()
482                 if movielistpreview.dialog is None:
483                         movielistpreview.gotSession(self.session)
484                 if idx == 0:
485                         movielistpreview.changeVisibility()
486                         self.showMenu()
487                 elif idx == 1:
488                         movielistpreview.dialog.hide()
489                         self.session.open(MovielistPreviewManualCreator, self.service)
490                 elif idx == 2:
491                         movielistpreview.dialog.hide()
492                         self.session.open(MovielistPreviewAutoCreator)
493                 else:
494                         movielistpreview.dialog.hide()
495                         self.session.open(MovielistPreviewPositioner)
496
497 ##############################################################################
498
499 SelectionChanged = MovieList.selectionChanged
500 def selectionChanged(instance):
501         SelectionChanged(instance)
502         curr = instance.getCurrent()
503         if curr and isinstance(curr, eServiceReference):
504                 movielistpreview.showPreview(curr.getPath())
505 MovieList.selectionChanged = selectionChanged
506
507 Hide = MovieSelection.hide
508 def hideMovieSelection(instance):
509         Hide(instance)
510         movielistpreview.hideDialog()
511 MovieSelection.hide = hideMovieSelection
512
513 Show = MovieSelection.show
514 def showMovieSelection(instance):
515         Show(instance)
516         movielistpreview.showDialog()
517 MovieSelection.show = showMovieSelection
518
519 ##############################################################################
520
521 def selectionChanged2(instance):
522         SelectionChanged2(instance)
523         curr = instance.getCurrent()
524         if curr and isinstance(curr, eServiceReference):
525                 movielistpreview.showPreview(curr.getPath())
526
527 def hideMovieSelection2(instance):
528         Hide2(instance)
529         movielistpreview.hideDialog()
530
531 def showMovieSelection2(instance):
532         Show2(instance)
533         movielistpreview.showDialog()
534
535 try:
536         from Plugins.Extensions.Suomipoeka.MovieList import MovieList as MovieList2
537         from Plugins.Extensions.Suomipoeka.MovieSelection import MovieSelectionSP
538         SelectionChanged2 = MovieList2.selectionChanged
539         MovieList2.selectionChanged = selectionChanged2
540         Hide2 = MovieSelectionSP.hide
541         MovieSelectionSP.hide = hideMovieSelection2
542         Show2 = MovieSelectionSP.show
543         MovieSelectionSP.show = showMovieSelection2
544 except ImportError:
545         print "[Movielist Preview] Could not import Suomipoeka Plugin, maybe not installed or too old version?"
546
547 ##############################################################################
548
549 def sessionstart(reason, **kwargs):
550         if reason == 0:
551                 movielistpreview.gotSession(kwargs["session"])
552
553 def main(session, service):
554         session.open(MovielistPreviewMenu, service)
555
556 ##############################################################################
557
558 def Plugins(**kwargs):
559         return [
560                 PluginDescriptor(where=[PluginDescriptor.WHERE_SESSIONSTART], fnc=sessionstart),
561                 PluginDescriptor(name=_("Movielist Preview"), description=_("Movielist Preview"), where=PluginDescriptor.WHERE_MOVIELIST, fnc=main)]