add PicturePlayer plugin
[vuplus_dvbapp] / lib / python / Plugins / Extensions / PicturePlayer / plugin.py
1 from enigma import *
2
3 from Screens.Screen import Screen
4 from Screens.ServiceInfo import ServiceInfoList, ServiceInfoListEntry
5 from Components.ActionMap import ActionMap, NumberActionMap
6 from Components.Pixmap import Pixmap, MovingPixmap
7 from Components.Label import Label
8
9 from Components.ConfigList import ConfigList
10 from Components.config import *
11
12 from Tools.Directories import resolveFilename, SCOPE_MEDIA
13 from Components.FileList import FileEntryComponent, FileList
14 from Components.AVSwitch import AVSwitch
15
16 from Plugins.Plugin import PluginDescriptor
17
18 import os
19
20 config.pic = ConfigSubsection()
21 config.pic.slidetime = ConfigInteger(default=10, limits=(5, 60))
22 config.pic.resize = ConfigSelection(default="0", choices = [("0", _("simple")), ("1", _("better"))])
23 config.pic.cache = ConfigEnableDisable(default=True)
24 config.pic.lastDir = ConfigText(default=resolveFilename(SCOPE_MEDIA))
25 config.pic.rotate = ConfigSelection(default="0", choices = [("0", _("none")), ("1", _("manual")), ("2", _("by Exif"))])
26
27 def getAspect():
28         val = AVSwitch().getAspectRatioSetting()
29         return val/2
30
31 #------------------------------------------------------------------------------------------
32
33 class ThumbView(Screen):
34         skin = """
35                 <screen position="0,0" size="720,576" flags="wfNoBorder" title="ThumbView" >
36                         <eLabel position="0,0" zPosition="0" size="720,576" backgroundColor="black" />
37                         <widget name="frame" position="50,63" size="190,200" pixmap="pic_frame.png" zPosition="1" alphatest="on" />
38                         <widget name="label0" position="55,240" size="180,20" font="Regular;13" halign="center" zPosition="2" transparent="1" />
39                         <widget name="label1" position="270,240" size="180,20" font="Regular;13" halign="center" zPosition="2" transparent="1" />
40                         <widget name="label2" position="485,240" size="180,20" font="Regular;13" halign="center" zPosition="2" transparent="1" />
41                         <widget name="label3" position="55,465" size="180,20" font="Regular;13" halign="center" zPosition="2" transparent="1" />
42                         <widget name="label4" position="270,465" size="180,20" font="Regular;13" halign="center" zPosition="2" transparent="1" />
43                         <widget name="label5" position="485,465" size="180,20" font="Regular;13" halign="center" zPosition="2" transparent="1" />
44                         <widget name="thumb0" position="55,68" size="180,160" zPosition="2" transparent="1"  />
45                         <widget name="thumb1" position="270,68" size="180,160" zPosition="2" transparent="1" />
46                         <widget name="thumb2" position="485,68" size="180,160" zPosition="2" transparent="1" />
47                         <widget name="thumb3" position="55,293" size="180,160" zPosition="2" transparent="1" />
48                         <widget name="thumb4" position="270,293" size="180,160" zPosition="2" transparent="1" />
49                         <widget name="thumb5" position="485,293" size="180,160" zPosition="2" transparent="1" />
50                 </screen>"""
51         
52         def __init__(self, session, filelist, name, path):
53                 self.skin = ThumbView.skin
54                 Screen.__init__(self, session)
55
56                 self["actions"] = ActionMap(["OkCancelActions", "DirectionActions", "MovieSelectionActions"],
57                 {
58                         "cancel": self.Exit,
59                         "ok": self.KeyOk,
60                         "showEventInfo": self.StartExif,
61                         "right": self.key_right,
62                         "left": self.key_left,
63                         "up": self.key_up,
64                         "down": self.key_down
65                 }, -1)
66                 
67                 for x in range(6):
68                         self["label"+str(x)] = Label()
69                         self["thumb"+str(x)] = Pixmap()
70                 self["frame"] = MovingPixmap()
71                 
72                 self.aspect = getAspect()
73                 self.path = path
74                 self.filelist = filelist
75                 self.currPage = -1
76                 self.index = 0
77                 self.old_index = 0
78                 self.thumblist = []
79                 self.thumbindex = 0
80                 self.list = []
81                 self.poslist = [[50,63],[265,63],[480,63],[50,288],[265,288],[480,288]]
82                 
83                 count=0
84                 pos=0
85                 for x in self.filelist:
86                         if x[0][1] == False:
87                                 self.list.append((x[0][0], self.path + x[0][0], count/6, pos, "(" + str(count+1) + ")  "))
88                                 pos += 1
89                                 if pos == 6:
90                                         pos = 0
91                                 if x[0][0] == name:
92                                         self.index = count
93                                 count += 1
94                 self.maxentry = len(self.list)-1
95                 
96                 self.ThumbTimer = eTimer()
97                 self.ThumbTimer.timeout.get().append(self.showThumb)
98
99                 self.fillPage()
100                 
101         def key_left(self):
102                 self.index -= 1
103                 if self.index < 0:
104                         self.index = self.maxentry
105                 self.fillPage()
106                 
107         def key_right(self):
108                 self.index += 1
109                 if self.index > self.maxentry:
110                         self.index = 0
111                 self.fillPage()
112                 
113         def key_up(self):
114                 self.index -= 3
115                 if self.index < 0:
116                         self.index = 0
117                 self.fillPage()
118                 
119         def key_down(self):
120                 self.index += 3
121                 if self.index > self.maxentry:
122                         self.index = self.maxentry
123                 self.fillPage()
124                 
125         def fillPage(self):
126                 self["frame"].moveTo(self.poslist[self.list[self.index][3]][0], self.poslist[self.list[self.index][3]][1], 1)
127                 self["frame"].startMoving()
128                 
129                 if self.list[self.index][2] != self.currPage:
130                         self.currPage = self.list[self.index][2]
131                         textlist = ["","","","","",""]
132                         self.thumblist = ["","","","","",""]
133                         
134                         for x in self.list:
135                                 if x[2] == self.currPage:
136                                         textlist[x[3]] = x[4] + x[0]
137                                         self.thumblist[x[3]] = x[0]
138                                         
139                         for x in range(6):
140                                 self["label"+str(x)].setText(textlist[x])
141                                 self["thumb"+str(x)].hide()
142                                 
143                         self.ThumbTimer.start(500, True)
144                 
145         def showThumb(self):
146                 if self.thumblist[self.thumbindex] != "":
147                         cachefile = ""
148                         if config.pic.cache.value:
149                                 cachedir = self.path + ".Thumbnails/"
150                                 if not os.path.exists(cachedir):
151                                         os.mkdir(cachedir)
152                                 cachefile = cachedir + self.thumblist[self.thumbindex] + str(180) + str(160) + str(self.aspect)
153
154                         ptr = loadPic(self.path + self.thumblist[self.thumbindex], 180, 160, self.aspect, int(config.pic.resize.value), int(config.pic.rotate.value),1, cachefile)
155                         if ptr != None:
156                                 self["thumb"+str(self.thumbindex)].show()
157                                 self["thumb"+str(self.thumbindex)].instance.setPixmap(ptr.__deref__())
158                         
159                         self.thumbindex += 1
160                         if self.thumbindex < 6:
161                                 self.ThumbTimer.start(500, True)
162                         else:
163                                 self.thumbindex = 0
164                 else:
165                         self.thumbindex = 0
166                 
167         def StartExif(self):
168                 self.session.open(ExifView, self.list[self.index][1], self.list[self.index][0])
169
170         def KeyOk(self):
171                 self.old_index = self.index
172                 self.session.openWithCallback(self.returnView ,PicView, self.filelist, self.list[self.index][0], self.path)
173                 
174         def returnView(self, val=0):
175                 self.index = val
176                 if self.old_index != self.index:
177                         self.fillPage()
178                 
179         def Exit(self):
180                 self.close(self.index)
181
182 #------------------------------------------------------------------------------------------
183
184 class PicView(Screen):
185         skin = """
186                 <screen position="0,0" size="720,576" flags="wfNoBorder" title="PicturePlayer" >
187                         <eLabel position="0,0" zPosition="0" size="720,576" backgroundColor="black" />
188                         <widget name="picture" position="80,50" size="560,450" zPosition="1" transparent="1" />
189                         <widget name="point" position="80,515" size="15,15" zPosition="1" pixmap="BlinkingPoint-fs8.png" alphatest="on" />
190                         <widget name="file" position="150,510" size="350,30" font="Regular;20" halign="center" zPosition="1" transparent="1" />
191                         <ePixmap position="500,515" size="36,20" pixmap="key_info-fs8.png" zPosition="1" alphatest="on" />
192                         <ePixmap position="550,515" size="20,20" pixmap="ico_mp_rewind.png"  zPosition="1" alphatest="on" />
193                         <widget name="play" position="575,515" size="20,20" pixmap="ico_mp_play.png"  zPosition="1" alphatest="on" />
194                         <widget name="pause" position="600,515" size="20,20" pixmap="ico_mp_pause.png"  zPosition="1" alphatest="on" />
195                         <ePixmap position="625,515" size="20,20" pixmap="ico_mp_forward.png"  zPosition="1" alphatest="on" />
196                 </screen>"""
197         
198         def __init__(self, session, filelist, name, path):
199                 self.skin = PicView.skin
200                 Screen.__init__(self, session)
201
202                 self["actions"] = ActionMap(["OkCancelActions", "ColorActions", "MovieSelectionActions"],
203                 {
204                         "cancel": self.Exit,
205                         "showEventInfo": self.StartExif,
206                         "green": self.Play,
207                         "yellow": self.Pause,
208                         "blue": self.nextPic,
209                         "red": self.prevPic
210                 }, -1)
211
212                 self.aspect = getAspect()
213                 self.blinking = False
214                 self.autoShow = True
215                 self.slideOn = False
216                 self.pauseOn = False
217                 self.index = 0
218                 self.list = []
219                 
220                 count=0
221                 for x in filelist:
222                         if x[0][1] == False:
223                                 self.list.append((x[0][0], path + x[0][0], 0))
224                                 if x[0][0] == name:
225                                         self.index = count
226                                 count += 1
227                 self.maxentry = len(self.list)-1
228
229                 self["file"] = Label(_("please wait, loading picture..."))
230                 self["picture"] = Pixmap()
231                 self["point"] = Pixmap()
232                 self["play"] = Pixmap()
233                 self["pause"] = Pixmap()
234                 
235                 self.decodeTimer = eTimer()
236                 self.decodeTimer.timeout.get().append(self.decodePic)
237                 self.decodeTimer.start(300, True)
238
239                 self.slideTimer = eTimer()
240                 self.slideTimer.timeout.get().append(self.slidePic)
241                 
242                 
243         def Pause(self):
244                 if self.slideOn:
245                         if self.pauseOn:
246                                 self.pauseOn=False
247                                 self["pause"].show()
248                         else:
249                                 self.pauseOn=True
250                                 self["play"].show()
251                                 self.slideValue = 0
252                 
253         def Play(self):
254                 if self.pauseOn == False:
255                         if self.slideOn:
256                                 self.slideOn=False
257                                 self["play"].show()
258                         else:
259                                 self.slideOn=True
260                                 self.slideTimer.start(1000, True)
261                         
262                         self.slideValue = int(config.pic.slidetime.value)
263                 
264         def slidePic(self):
265                 if self.slideOn == True and self.pauseOn == False:
266                         self.blinkingWidget("play")
267                         self.slideValue -= 1
268                         if self.slideValue <= 0:
269                                 self.slideValue = int(config.pic.slidetime.value)
270                                 self.nextPic()
271                 
272                         self.slideTimer.start(1000, True)
273
274                 if self.pauseOn:
275                         self.blinkingWidget("pause")
276                         self.slideTimer.start(1000, True)
277
278         def decodePic(self):
279                 self.currPic = loadPic(self.list[self.index][1], 560, 450, self.aspect, int(config.pic.resize.value), int(config.pic.rotate.value),1)
280                 self["point"].hide()
281                 if self.autoShow:
282                         self.showPic()
283                         self.autoShow = False
284                 
285         def showPic(self):
286                 if self.currPic != None:
287                         self.old = self.index
288                         self["file"].setText(self.list[self.old][0] + "  (" + str(self.old+1) + "/" + str(self.maxentry+1) + ")")
289                         self["picture"].instance.setPixmap(self.currPic.__deref__())
290
291                 self.next()
292                 self["point"].show()
293                 self.decodeTimer.start(300, True)
294                 
295         def nextPic(self):
296                 self.showPic()
297                 
298         def prevPic(self):
299                 self.index = self.old
300                 self.prev()
301                 self.autoShow = True
302                 self["point"].show()
303                 self.decodeTimer.start(300, True)
304                 
305         def next(self):
306                 self.index += 1
307                 if self.index > self.maxentry:
308                         self.index = 0
309
310         def prev(self):
311                 self.index -= 1
312                 if self.index < 0:
313                         self.index = self.maxentry
314                         
315         def blinkingWidget(self, name):
316                 if self.blinking:
317                         self.blinking=False
318                         self[name].show()
319                 else:
320                         self.blinking=True
321                         self[name].hide()
322
323         def StartExif(self):
324                 if self.pauseOn == False:
325                         self.Pause()
326                 self.session.openWithCallback(self.StopExif ,ExifView, self.list[self.old][1], self.list[self.old][0])
327                 
328         def StopExif(self):
329                 if self.pauseOn:
330                         self.Pause()
331
332         def Exit(self):
333                 self.close(self.old)
334
335 #------------------------------------------------------------------------------------------
336
337 class ExifView(Screen):
338         skin = """
339                 <screen position="80,130" size="560,320" title="Exif-Data" >
340                         <widget name="exiflist" position="5,5" size="550,310" selectionDisabled="1" />
341                 </screen>"""
342         
343         def __init__(self, session, fullname, name):
344                 self.skin = ExifView.skin
345                 Screen.__init__(self, session)
346
347                 self["actions"] = ActionMap(["OkCancelActions"],
348                 {
349                         "cancel": self.close
350                 }, -1)
351                 
352                 dlist = ["Name:", "EXIF-Version:", "Camera-Make:", "Camera-Model:", "Date/Time:", "User Comments:", "Width / Height:", "Orientation:", "Metering Mode:", "Exposure Program:", "Light Source:", "Flash used:", "CompressedBitsPerPixel:", "ISO Speed Rating:", "X-Resolution:", "Y-Resolution:", "Resolution Unit:", "Brightness:", "Exposure Time:", "Exposure Bias:", "Distance:", "CCD-Width:", "ApertureFNumber:"]
353                 tlist = [ ]
354                 self["exiflist"] = ServiceInfoList(tlist)
355                 tlist.append(ServiceInfoListEntry(dlist[0], name))
356                 count=1
357                 for x in getExif(fullname):
358                         tlist.append(ServiceInfoListEntry(dlist[count], x))
359                         count += 1
360
361 #------------------------------------------------------------------------------------------
362
363 class PicSetup(Screen):
364         skin = """
365                 <screen position="160,220" size="400,120" title="Settings" >
366                         <widget name="liste" position="10,10" size="380,100" />
367                 </screen>"""
368         
369         def __init__(self, session):
370                 self.skin = PicSetup.skin
371                 Screen.__init__(self, session)
372
373                 self["actions"] = NumberActionMap(["SetupActions"],
374                 {
375                         "cancel": self.close,
376                         "left": self.keyLeft,
377                         "right": self.keyRight,
378                         "0": self.keyNumber,
379                         "1": self.keyNumber,
380                         "2": self.keyNumber,
381                         "3": self.keyNumber,
382                         "4": self.keyNumber,
383                         "5": self.keyNumber,
384                         "6": self.keyNumber,
385                         "7": self.keyNumber,
386                         "8": self.keyNumber,
387                         "9": self.keyNumber
388                 }, -1)
389                 
390                 self.list = []
391                 self["liste"] = ConfigList(self.list)
392                 self.list.append(getConfigListEntry(_("Slideshow Interval (sec.)"), config.pic.slidetime))
393                 self.list.append(getConfigListEntry(_("Scaling Mode"), config.pic.resize))
394                 self.list.append(getConfigListEntry(_("Cache Thumbnails"), config.pic.cache))
395                 #self.list.append(getConfigListEntry(_("Rotate Picture"), config.pic.rotate))
396                 
397         def keyLeft(self):
398                 self["liste"].handleKey(KEY_LEFT)
399
400         def keyRight(self):
401                 self["liste"].handleKey(KEY_RIGHT)
402                 
403         def keyNumber(self, number):
404                 self["liste"].handleKey(KEY_0 + number)
405
406
407 #------------------------------------------------------------------------------------------
408
409 class picmain(Screen):
410         skin = """
411                 <screen position="160,90" size="400,390" title="PicturePlayer" >
412                         <ePixmap position="10,40" size="36,20" pixmap="key_menu-fs8.png" transparent="1" alphatest="on" />
413                         <ePixmap position="10,70" size="36,20" pixmap="key_info-fs8.png" transparent="1" alphatest="on" />
414                         <ePixmap position="12,100" size="36,20" pixmap="key_red-fs8.png" transparent="1" alphatest="on" />
415                         <eLabel text="Settings" position="60,40" size="120,25" font="Regular;20" transparent="1" />
416                         <eLabel text="Exif-Data" position="60,70" size="120,25" font="Regular;20" transparent="1" />
417                         <eLabel text="Thumbnails" position="60,100" size="120,25" font="Regular;20" transparent="1" />
418                         <widget name="thumbnail" position="200,5" size="180,160" alphatest="on" />
419                         <widget name="filelist" position="5,170" zPosition="2" size="390,210" scrollbarMode="showOnDemand" />
420                 </screen>"""
421         
422         def __init__(self, session):
423                 self.skin = picmain.skin
424                 Screen.__init__(self, session)
425
426                 self["actions"] = ActionMap(["OkCancelActions", "DirectionActions", "ColorActions", "MovieSelectionActions"],
427                 {
428                         "ok": self.KeyOk,
429                         "cancel": self.Exit,
430                         "right": self.rightDown,
431                         "left": self.leftUp,
432                         "up": self.up,
433                         "down": self.down,
434                         "showEventInfo": self.StartExif,
435                         "contextMenu": self.Settings,
436                         "red": self.StartThumb
437                 }, -1)
438                 
439                 self.aspect = getAspect()
440                 self.currDir = config.pic.lastDir.value
441                 if not os.path.exists(self.currDir):
442                         self.currDir = "/"
443                 
444                 self.filelist = FileList(self.currDir, matchingPattern = "(?i)^.*\.(jpeg|jpg|png|bmp)")
445                 self["filelist"] = self.filelist
446                 self["thumbnail"] = Pixmap()
447                 
448                 self.ThumbTimer = eTimer()
449                 self.ThumbTimer.timeout.get().append(self.showThumb)
450                 self.ThumbTimer.start(500, True)
451                 
452         def up(self):
453                 self["filelist"].up()
454                 self.ThumbTimer.start(1500, True)
455
456         def down(self):
457                 self["filelist"].down()
458                 self.ThumbTimer.start(1500, True)
459                 
460         def leftUp(self):
461                 self["filelist"].pageUp()
462                 self.ThumbTimer.start(1500, True)
463                 
464         def rightDown(self):
465                 self["filelist"].pageDown()
466                 self.ThumbTimer.start(1500, True)
467
468         def showThumb(self):
469                 if not self.filelist.canDescent():
470                         cachefile = ""
471                         if config.pic.cache.value:
472                                 cachedir = self.currDir + ".Thumbnails/"
473                                 if not os.path.exists(cachedir):
474                                         os.mkdir(cachedir)
475                                 cachefile = cachedir + self.filelist.getSelection()[0] + str(180) + str(160) + str(self.aspect)
476
477                         ptr = loadPic(self.currDir + self.filelist.getSelection()[0], 180, 160, self.aspect, int(config.pic.resize.value), 0, 0, cachefile)
478                         if ptr != None:
479                                 self["thumbnail"].show()
480                                 self["thumbnail"].instance.setPixmap(ptr.__deref__())
481                 else:
482                         self["thumbnail"].hide()
483
484         def KeyOk(self):
485                 if self.filelist.canDescent():
486                         self.currDir = self.filelist.getSelection()[0]
487                         self.filelist.descent()
488                 else:
489                         self.session.openWithCallback(self.returnVal, PicView, self.filelist.getFileList(), self.filelist.getSelection()[0], self.currDir)
490                         
491         def StartThumb(self):
492                 self.session.openWithCallback(self.returnVal, ThumbView, self.filelist.getFileList(), self.filelist.getSelection()[0], self.currDir)
493
494         def returnVal(self, val=0):
495                 print val
496
497         def StartExif(self):
498                 if not self.filelist.canDescent():
499                         self.session.open(ExifView, self.currDir + self.filelist.getSelection()[0], self.filelist.getSelection()[0])
500
501         def Settings(self):
502                 self.session.open(PicSetup)
503         
504         def Exit(self):
505                 config.pic.lastDir.value = self.currDir
506                 config.pic.save()
507                 self.close()
508
509 #------------------------------------------------------------------------------------------
510
511 def main(session, **kwargs):
512         session.open(picmain)
513
514 def Plugins(**kwargs):
515         return PluginDescriptor(name="PicturePlayer", description="Picture Viewer (BMP, PNG, JPG)", icon="pictureplayer.png", where = PluginDescriptor.WHERE_PLUGINMENU, fnc=main)