1 from enigma import ePicLoad, eTimer, getDesktop
3 from Screens.Screen import Screen
4 from Tools.Directories import resolveFilename, pathExists, fileExists, SCOPE_MEDIA
5 from Plugins.Plugin import PluginDescriptor
7 from Components.Pixmap import Pixmap, MovingPixmap
8 from Components.ActionMap import ActionMap, NumberActionMap
9 from Components.Label import Label
10 from Components.Button import Button
11 from Components.FileList import FileList
12 from Components.AVSwitch import AVSwitch
13 from Components.Sources.List import List
14 from Components.ConfigList import ConfigList
16 from Components.config import config, ConfigSubsection, ConfigInteger, ConfigSelection, ConfigText, ConfigEnableDisable, KEY_LEFT, KEY_RIGHT, KEY_0, getConfigListEntry
19 return AVSwitch().getFramebufferScale()
21 config.pic = ConfigSubsection()
22 config.pic.framesize = ConfigInteger(default=30, limits=(5, 99))
23 config.pic.slidetime = ConfigInteger(default=10, limits=(10, 60))
24 config.pic.resize = ConfigSelection(default="1", choices = [("0", _("simple")), ("1", _("better"))])
25 config.pic.cache = ConfigEnableDisable(default=True)
26 config.pic.lastDir = ConfigText(default=resolveFilename(SCOPE_MEDIA))
27 config.pic.infoline = ConfigEnableDisable(default=True)
28 config.pic.loop = ConfigEnableDisable(default=True)
29 config.pic.bgcolor = ConfigSelection(default="#00000000", choices = [("#00000000", _("black")),("#009eb9ff", _("blue")),("#00ff5a51", _("red")), ("#00ffe875", _("yellow")), ("#0038FF48", _("green"))])
30 config.pic.textcolor = ConfigSelection(default="#0038FF48", choices = [("#00000000", _("black")),("#009eb9ff", _("blue")),("#00ff5a51", _("red")), ("#00ffe875", _("yellow")), ("#0038FF48", _("green"))])
32 class picshow(Screen):
33 def __init__(self, session):
34 self.skin = """<screen position="80,80" size="560,440" title="PicturePlayer" >
35 <ePixmap position="0,0" size="140,40" pixmap="skin_default/buttons/red.png" alphatest="on" />
36 <ePixmap position="140,0" size="140,40" pixmap="skin_default/buttons/green.png" alphatest="on" />
37 <ePixmap position="280,0" size="140,40" pixmap="skin_default/buttons/yellow.png" alphatest="on" />
38 <ePixmap position="420,0" size="140,40" pixmap="skin_default/buttons/blue.png" alphatest="on" />
39 <widget name="key_red" position="0,0" size="140,40" font="Regular;20" backgroundColor="#9f1313" zPosition="2" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
40 <widget name="key_green" position="140,0" size="140,40" font="Regular;20" backgroundColor="#1f771f" zPosition="2" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
41 <widget name="key_yellow" position="280,0" size="140,40" font="Regular;20" backgroundColor="#a08500" zPosition="2" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
42 <widget name="key_blue" position="420,0" size="140,40" font="Regular;20" backgroundColor="#18188b" zPosition="2" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
43 <widget name="label" position="5,55" size="350,140" font="Regular;19" />
44 <widget name="thn" position="360,40" size="180,160" alphatest="on" />
45 <widget name="filelist" position="5,205" zPosition="2" size="550,230" scrollbarMode="showOnDemand" />
48 Screen.__init__(self, session)
50 self["actions"] = ActionMap(["OkCancelActions", "ColorActions", "DirectionActions"],
52 "cancel": self.KeyExit,
54 "yellow": self.KeyYellow,
59 self["key_red"] = Button(_("Thumbnails"))
60 self["key_green"] = Button()
61 self["key_yellow"] = Button(_("Exif"))
62 self["key_blue"] = Button(_("Setup"))
63 self["label"] = Label()
64 self["thn"] = Pixmap()
66 currDir = config.pic.lastDir.value
67 if not pathExists(currDir):
70 self.filelist = FileList(currDir, matchingPattern = "(?i)^.*\.(jpeg|jpg|jpe|png|bmp|gif)")
71 self["filelist"] = self.filelist
72 self["filelist"].onSelectionChanged.append(self.selectionChanged)
74 self.ThumbTimer = eTimer()
75 self.ThumbTimer.callback.append(self.showThumb)
77 self.picload = ePicLoad()
78 self.picload.PictureData.get().append(self.showPic)
80 self.onLayoutFinish.append(self.setConf)
82 def showPic(self, picInfo=""):
83 ptr = self.picload.getData()
85 self["thn"].instance.setPixmap(ptr.__deref__())
88 text = picInfo.split('\n',1)
89 self["label"].setText(text[1])
93 if not self.filelist.canDescent():
94 if self.filelist.getCurrentDirectory() and self.filelist.getFilename():
95 if self.picload.getThumbnail(self.filelist.getCurrentDirectory() + self.filelist.getFilename()) == 1:
96 self.ThumbTimer.start(500, True)
98 def selectionChanged(self):
99 if not self.filelist.canDescent():
100 self.ThumbTimer.start(500, True)
106 #if not self.filelist.canDescent():
107 self.session.openWithCallback(self.callbackView, Pic_Thumb, self.filelist.getFileList(), self.filelist.getSelectionIndex(), self.filelist.getCurrentDirectory())
110 if not self.filelist.canDescent():
111 self.session.open(Pic_Exif, self.picload.getInfo(self.filelist.getCurrentDirectory() + self.filelist.getFilename()))
114 self.session.openWithCallback(self.setConf ,Pic_Setup)
117 if self.filelist.canDescent():
118 self.filelist.descent()
120 self.session.openWithCallback(self.callbackView, Pic_Full_View, self.filelist.getFileList(), self.filelist.getSelectionIndex(), self.filelist.getCurrentDirectory())
124 #0=Width 1=Height 2=Aspect 3=use_cache 4=resize_type 5=Background(#AARRGGBB)
125 self.picload.setPara((self["thn"].instance.size().width(), self["thn"].instance.size().height(), sc[0], sc[1], config.pic.cache.value, int(config.pic.resize.value), "#00000000"))
127 def callbackView(self, val=0):
129 self.filelist.moveToIndex(val)
134 if self.filelist.getCurrentDirectory() is None:
135 config.pic.lastDir.value = "/"
137 config.pic.lastDir.value = self.filelist.getCurrentDirectory()
142 #------------------------------------------------------------------------------------------
144 class Pic_Setup(Screen):
145 def __init__(self, session):
146 self.skin = """<screen position="120,180" size="480,210" title="Settings" >
147 <widget name="liste" position="5,5" size="470,200" />
149 Screen.__init__(self, session)
151 self["actions"] = NumberActionMap(["SetupActions"],
153 "cancel": self.close,
154 "left": self.keyLeft,
155 "right": self.keyRight,
169 self["liste"] = ConfigList(list)
170 list.append(getConfigListEntry(_("Slideshow Interval (sec.)"), config.pic.slidetime))
171 list.append(getConfigListEntry(_("Scaling Mode"), config.pic.resize))
172 list.append(getConfigListEntry(_("Cache Thumbnails"), config.pic.cache))
173 list.append(getConfigListEntry(_("show Infoline"), config.pic.infoline))
174 list.append(getConfigListEntry(_("Frame size in full view"), config.pic.framesize))
175 list.append(getConfigListEntry(_("slide picture in loop"), config.pic.loop))
176 list.append(getConfigListEntry(_("backgroundcolor"), config.pic.bgcolor))
177 list.append(getConfigListEntry(_("textcolor"), config.pic.textcolor))
180 self["liste"].handleKey(KEY_LEFT)
183 self["liste"].handleKey(KEY_RIGHT)
185 def keyNumber(self, number):
186 self["liste"].handleKey(KEY_0 + number)
188 #---------------------------------------------------------------------------
190 class Pic_Exif(Screen):
191 def __init__(self, session, exiflist):
192 self.skin = """<screen position="80,120" size="560,360" title="Info" >
193 <widget source="menu" render="Listbox" position="0,0" size="560,360" scrollbarMode="showOnDemand" selectionDisabled="1" >
194 <convert type="TemplatedMultiContent">
195 {"template": [ MultiContentEntryText(pos = (5, 5), size = (250, 30), flags = RT_HALIGN_LEFT, text = 0), MultiContentEntryText(pos = (260, 5), size = (290, 30), flags = RT_HALIGN_LEFT, text = 1)], "fonts": [gFont("Regular", 20)], "itemHeight": 30 }
199 Screen.__init__(self, session)
201 self["actions"] = ActionMap(["OkCancelActions"],
206 exifdesc = [_("filename")+':', "EXIF-Version:", "Make:", "Camera:", "Date/Time:", "Width / Height:", "Flash used:", "Orientation:", "User Comments:", "Metering Mode:", "Exposure Program:", "Light Source:", "CompressedBitsPerPixel:", "ISO Speed Rating:", "X-Resolution:", "Y-Resolution:", "Resolution Unit:", "Brightness:", "Exposure Time:", "Exposure Bias:", "Distance:", "CCD-Width:", "ApertureFNumber:"]
209 for x in range(len(exiflist)):
211 list.append((exifdesc[x], exiflist[x]))
213 name = exiflist[x].split('/')[-1]
214 list.append((exifdesc[x], name))
215 self["menu"] = List(list)
217 #----------------------------------------------------------------------------------------
225 class Pic_Thumb(Screen):
226 def __init__(self, session, piclist, lastindex, path):
228 self.textcolor = config.pic.textcolor.value
229 self.color = config.pic.bgcolor.value
236 size_w = getDesktop(0).size().width()
237 size_h = getDesktop(0).size().height()
238 self.thumbsX = size_w / (self.spaceX + self.picX) # thumbnails in X
239 self.thumbsY = size_h / (self.spaceY + self.picY) # thumbnails in Y
240 self.thumbsC = self.thumbsX * self.thumbsY # all thumbnails
242 self.positionlist = []
246 for x in range(self.thumbsC):
247 posY = x / self.thumbsX
249 if posX >= self.thumbsX:
252 absX = self.spaceX + (posX*(self.spaceX + self.picX))
253 absY = self.spaceY + (posY*(self.spaceY + self.picY))
254 self.positionlist.append((absX, absY))
255 skincontent += "<widget name=\"label" + str(x) + "\" position=\"" + str(absX+5) + "," + str(absY+self.picY-textsize) + "\" size=\"" + str(self.picX - 10) + "," + str(textsize) + "\" font=\"Regular;14\" zPosition=\"2\" transparent=\"1\" noWrap=\"1\" foregroundColor=\"" + self.textcolor + "\" />"
257 skincontent += "<widget name=\"thumb" + str(x) + "\" position=\"" + str(absX+5)+ "," + str(absY+5) + "\" size=\"" + str(self.picX -10) + "," + str(self.picY - (textsize*2)) + "\" zPosition=\"2\" transparent=\"1\" alphatest=\"on\" />"
260 # Screen, backgroundlabel and MovingPixmap
261 self.skin = "<screen position=\"0,0\" size=\"" + str(size_w) + "," + str(size_h) + "\" flags=\"wfNoBorder\" > \
262 <eLabel position=\"0,0\" zPosition=\"0\" size=\""+ str(size_w) + "," + str(size_h) + "\" backgroundColor=\"" + self.color + "\" /><widget name=\"frame\" position=\"35,30\" size=\"190,200\" pixmap=\"pic_frame.png\" zPosition=\"1\" alphatest=\"on\" />" + skincontent + "</screen>"
264 Screen.__init__(self, session)
266 self["actions"] = ActionMap(["OkCancelActions", "ColorActions", "DirectionActions", "MovieSelectionActions"],
270 "left": self.key_left,
271 "right": self.key_right,
273 "down": self.key_down,
274 "showEventInfo": self.StartExif,
277 self["frame"] = MovingPixmap()
278 for x in range(self.thumbsC):
279 self["label"+str(x)] = Label()
280 self["thumb"+str(x)] = Pixmap()
282 self.Thumbnaillist = []
285 self.dirlistcount = 0
293 self.filelist.append((index, framePos, Page, x[0][0], path + x[0][0]))
296 if framePos > (self.thumbsC -1):
300 self.dirlistcount += 1
302 self.maxentry = len(self.filelist)-1
303 self.index = lastindex - self.dirlistcount
307 self.picload = ePicLoad()
308 self.picload.PictureData.get().append(self.showPic)
310 self.onLayoutFinish.append(self.setPicloadConf)
312 self.ThumbTimer = eTimer()
313 self.ThumbTimer.callback.append(self.showPic)
315 def setPicloadConf(self):
317 self.picload.setPara([self["thumb0"].instance.size().width(), self["thumb0"].instance.size().height(), sc[0], sc[1], config.pic.cache.value, int(config.pic.resize.value), self.color])
320 def paintFrame(self):
321 #print "index=" + str(self.index)
322 if self.maxentry < self.index or self.index < 0:
325 pos = self.positionlist[self.filelist[self.index][T_FRAME_POS]]
326 self["frame"].moveTo( pos[0], pos[1], 1)
327 self["frame"].startMoving()
329 if self.currPage != self.filelist[self.index][T_PAGE]:
330 self.currPage = self.filelist[self.index][T_PAGE]
334 self.Thumbnaillist = []
335 #clear Labels and Thumbnail
336 for x in range(self.thumbsC):
337 self["label"+str(x)].setText("")
338 self["thumb"+str(x)].hide()
339 #paint Labels and fill Thumbnail-List
340 for x in self.filelist:
341 if x[T_PAGE] == self.currPage:
342 self["label"+str(x[T_FRAME_POS])].setText("(" + str(x[T_INDEX]+1) + ") " + x[T_NAME])
343 self.Thumbnaillist.append([0, x[T_FRAME_POS], x[T_FULL]])
345 #paint Thumbnail start
348 def showPic(self, picInfo=""):
349 for x in range(len(self.Thumbnaillist)):
350 if self.Thumbnaillist[x][0] == 0:
351 if self.picload.getThumbnail(self.Thumbnaillist[x][2]) == 1: #zu tun probier noch mal
352 self.ThumbTimer.start(500, True)
354 self.Thumbnaillist[x][0] = 1
356 elif self.Thumbnaillist[x][0] == 1:
357 self.Thumbnaillist[x][0] = 2
358 ptr = self.picload.getData()
360 self["thumb" + str(self.Thumbnaillist[x][1])].instance.setPixmap(ptr.__deref__())
361 self["thumb" + str(self.Thumbnaillist[x][1])].show()
366 self.index = self.maxentry
371 if self.index > self.maxentry:
376 self.index -= self.thumbsX
378 self.index =self.maxentry
382 self.index += self.thumbsX
383 if self.index > self.maxentry:
388 if self.maxentry < 0:
390 self.session.open(Pic_Exif, self.picload.getInfo(self.filelist[self.index][T_FULL]))
393 if self.maxentry < 0:
395 self.old_index = self.index
396 self.session.openWithCallback(self.callbackView, Pic_Full_View, self.filelist, self.index, self.path)
398 def callbackView(self, val=0):
400 if self.old_index != self.index:
404 self.close(self.index + self.dirlistcount)
406 #---------------------------------------------------------------------------
408 class Pic_Full_View(Screen):
409 def __init__(self, session, filelist, index, path):
411 self.textcolor = config.pic.textcolor.value
412 self.bgcolor = config.pic.bgcolor.value
413 space = config.pic.framesize.value
414 size_w = getDesktop(0).size().width()
415 size_h = getDesktop(0).size().height()
417 self.skin = "<screen position=\"0,0\" size=\"" + str(size_w) + "," + str(size_h) + "\" flags=\"wfNoBorder\" > \
418 <eLabel position=\"0,0\" zPosition=\"0\" size=\""+ str(size_w) + "," + str(size_h) + "\" backgroundColor=\""+ self.bgcolor +"\" /><widget name=\"pic\" position=\"" + str(space) + "," + str(space) + "\" size=\"" + str(size_w-(space*2)) + "," + str(size_h-(space*2)) + "\" zPosition=\"1\" alphatest=\"on\" /> \
419 <widget name=\"point\" position=\""+ str(space+5) + "," + str(space+2) + "\" size=\"20,20\" zPosition=\"2\" pixmap=\"skin_default/icons/record.png\" alphatest=\"on\" /> \
420 <widget name=\"play_icon\" position=\""+ str(space+25) + "," + str(space+2) + "\" size=\"20,20\" zPosition=\"2\" pixmap=\"skin_default/icons/ico_mp_play.png\" alphatest=\"on\" /> \
421 <widget name=\"file\" position=\""+ str(space+45) + "," + str(space) + "\" size=\""+ str(size_w-(space*2)-50) + ",25\" font=\"Regular;20\" halign=\"left\" foregroundColor=\"" + self.textcolor + "\" zPosition=\"2\" noWrap=\"1\" transparent=\"1\" /></screen>"
423 Screen.__init__(self, session)
425 self["actions"] = ActionMap(["OkCancelActions", "ColorActions", "DirectionActions", "MovieSelectionActions"],
428 "green": self.PlayPause,
429 "yellow": self.PlayPause,
430 "blue": self.nextPic,
432 "left": self.prevPic,
433 "right": self.nextPic,
434 "showEventInfo": self.StartExif,
437 self["point"] = Pixmap()
438 self["pic"] = Pixmap()
439 self["play_icon"] = Pixmap()
440 self["file"] = Label(_("please wait, loading picture..."))
444 self.lastindex = index
447 self.dirlistcount = 0
450 if len(filelist[0]) == 3: #orig. filelist
452 self.filelist.append(path + x[0][0])
454 self.dirlistcount += 1
455 elif len(filelist[0]) == 2: #scanlist
457 self.filelist.append(x[0][0])
459 self.dirlistcount += 1
460 else: # thumbnaillist
461 self.filelist.append(x[T_FULL])
463 self.maxentry = len(self.filelist)-1
464 self.index = index - self.dirlistcount
468 self.picload = ePicLoad()
469 self.picload.PictureData.get().append(self.finish_decode)
471 self.slideTimer = eTimer()
472 self.slideTimer.callback.append(self.slidePic)
474 if self.maxentry >= 0:
475 self.onLayoutFinish.append(self.setPicloadConf)
477 def setPicloadConf(self):
479 self.picload.setPara([self["pic"].instance.size().width(), self["pic"].instance.size().height(), sc[0], sc[1], 0, int(config.pic.resize.value), self.bgcolor])
481 self["play_icon"].hide()
482 if config.pic.infoline.value == False:
486 def ShowPicture(self):
487 if self.shownow and len(self.currPic):
489 self["file"].setText(self.currPic[0])
490 self.lastindex = self.currPic[1]
491 self["pic"].instance.setPixmap(self.currPic[2].__deref__())
497 def finish_decode(self, picInfo=""):
499 ptr = self.picload.getData()
503 text = picInfo.split('\n',1)
504 text = "(" + str(self.index+1) + "/" + str(self.maxentry+1) + ") " + text[0].split('/')[-1]
508 self.currPic.append(text)
509 self.currPic.append(self.index)
510 self.currPic.append(ptr)
513 def start_decode(self):
514 self.picload.startDecode(self.filelist[self.index])
519 if self.index > self.maxentry:
525 self.index = self.maxentry
528 print "slide to next Picture index=" + str(self.lastindex)
529 if config.pic.loop.value==False and self.lastindex == self.maxentry:
535 if self.slideTimer.isActive():
536 self.slideTimer.stop()
537 self["play_icon"].hide()
539 self.slideTimer.start(config.pic.slidetime.value*1000)
540 self["play_icon"].show()
545 self.index = self.lastindex
555 if self.maxentry < 0:
557 self.session.open(Pic_Exif, self.picload.getInfo(self.filelist[self.lastindex]))
561 self.close(self.lastindex + self.dirlistcount)
563 #------------------------------------------------------------------------------------------
565 def main(session, **kwargs):
566 session.open(picshow)
568 def filescan_open(list, session, **kwargs):
569 # Recreate List as expected by PicView
570 filelist = [((file.path, False), None) for file in list]
571 session.open(Pic_Full_View, filelist, 0, file.path)
573 def filescan(**kwargs):
574 from Components.Scanner import Scanner, ScanPath
576 # Overwrite checkFile to only detect local
577 class LocalScanner(Scanner):
578 def checkFile(self, file):
579 return fileExists(file.path)
582 LocalScanner(mimetypes = ["image/jpeg", "image/png", "image/gif", "image/bmp"],
585 ScanPath(path = "DCIM", with_subdirs = True),
586 ScanPath(path = "", with_subdirs = False),
589 description = "View Photos...",
590 openfnc = filescan_open,
593 def Plugins(**kwargs):
595 [PluginDescriptor(name=_("PicturePlayer"), description=_("fileformats (BMP, PNG, JPG, GIF)"), icon="pictureplayer.png", where = PluginDescriptor.WHERE_PLUGINMENU, fnc=main),
596 PluginDescriptor(name=_("PicturePlayer"), where = PluginDescriptor.WHERE_FILESCAN, fnc = filescan)]