1 from enigma import ePicLoad, eTimer, getDesktop
3 from Screens.Screen import Screen
4 from Tools.Directories import resolveFilename, pathExists, 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
18 def getAspectforPic():
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.picload.getThumbnail(self.filelist.getCurrentDirectory() + self.filelist.getFilename()) == 1:
95 self.ThumbTimer.start(500, True)
97 def selectionChanged(self):
98 if not self.filelist.canDescent():
99 self.ThumbTimer.start(500, True)
105 #if not self.filelist.canDescent():
106 self.session.openWithCallback(self.callbackView, Pic_Thumb, self.filelist.getFileList(), self.filelist.getSelectionIndex(), self.filelist.getCurrentDirectory())
109 if not self.filelist.canDescent():
110 self.session.open(Pic_Exif, self.picload.getInfo(self.filelist.getCurrentDirectory() + self.filelist.getFilename()))
113 self.session.openWithCallback(self.setConf ,Pic_Setup)
116 if self.filelist.canDescent():
117 self.filelist.descent()
119 self.session.openWithCallback(self.callbackView, Pic_Full_View, self.filelist.getFileList(), self.filelist.getSelectionIndex(), self.filelist.getCurrentDirectory())
122 #0=Width 1=Height 2=Aspect 3=use_cache 4=resize_type 5=Background(#AARRGGBB)
123 self.picload.setPara([self["thn"].instance.size().width(), self["thn"].instance.size().height(), getAspectforPic(), config.pic.cache.value, int(config.pic.resize.value), "#00000000"])
125 def callbackView(self, val=0):
127 self.filelist.moveToIndex(val)
132 if self.filelist.getCurrentDirectory() is None:
133 config.pic.lastDir.value = "/"
135 config.pic.lastDir.value = self.filelist.getCurrentDirectory()
140 #------------------------------------------------------------------------------------------
142 class Pic_Setup(Screen):
143 def __init__(self, session):
144 self.skin = """<screen position="120,180" size="480,210" title="Settings" >
145 <widget name="liste" position="5,5" size="470,200" />
147 Screen.__init__(self, session)
149 self["actions"] = NumberActionMap(["SetupActions"],
151 "cancel": self.close,
152 "left": self.keyLeft,
153 "right": self.keyRight,
167 self["liste"] = ConfigList(list)
168 list.append(getConfigListEntry(_("Slideshow Interval (sec.)"), config.pic.slidetime))
169 list.append(getConfigListEntry(_("Scaling Mode"), config.pic.resize))
170 list.append(getConfigListEntry(_("Cache Thumbnails"), config.pic.cache))
171 list.append(getConfigListEntry(_("show Infoline"), config.pic.infoline))
172 list.append(getConfigListEntry(_("Frame size in full view"), config.pic.framesize))
173 list.append(getConfigListEntry(_("slide picture in loop"), config.pic.loop))
174 list.append(getConfigListEntry(_("backgroundcolor"), config.pic.bgcolor))
175 list.append(getConfigListEntry(_("textcolor"), config.pic.textcolor))
178 self["liste"].handleKey(KEY_LEFT)
181 self["liste"].handleKey(KEY_RIGHT)
183 def keyNumber(self, number):
184 self["liste"].handleKey(KEY_0 + number)
186 #---------------------------------------------------------------------------
188 class Pic_Exif(Screen):
189 def __init__(self, session, exiflist):
190 self.skin = """<screen position="80,120" size="560,360" title="Info" >
191 <widget source="menu" render="Listbox" position="0,0" size="560,360" scrollbarMode="showOnDemand" selectionDisabled="1" >
192 <convert type="TemplatedMultiContent">
193 {"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 }
197 Screen.__init__(self, session)
199 self["actions"] = ActionMap(["OkCancelActions"],
204 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:"]
207 for x in range(len(exiflist)):
209 list.append((exifdesc[x], exiflist[x]))
211 name = exiflist[x].split('/')[-1]
212 list.append((exifdesc[x], name))
213 self["menu"] = List(list)
215 #----------------------------------------------------------------------------------------
223 class Pic_Thumb(Screen):
224 def __init__(self, session, piclist, lastindex, path):
226 self.textcolor = config.pic.textcolor.value
227 self.color = config.pic.bgcolor.value
234 size_w = getDesktop(0).size().width()
235 size_h = getDesktop(0).size().height()
236 self.thumbsX = size_w / (self.spaceX + self.picX) # thumbnails in X
237 self.thumbsY = size_h / (self.spaceY + self.picY) # thumbnails in Y
238 self.thumbsC = self.thumbsX * self.thumbsY # all thumbnails
240 self.positionlist = []
244 for x in range(self.thumbsC):
245 posY = x / self.thumbsX
247 if posX >= self.thumbsX:
250 absX = self.spaceX + (posX*(self.spaceX + self.picX))
251 absY = self.spaceY + (posY*(self.spaceY + self.picY))
252 self.positionlist.append((absX, absY))
253 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 + "\" />"
255 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\" />"
258 # Screen, backgroundlabel and MovingPixmap
259 self.skin = "<screen position=\"0,0\" size=\"" + str(size_w) + "," + str(size_h) + "\" flags=\"wfNoBorder\" > \
260 <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>"
262 Screen.__init__(self, session)
264 self["actions"] = ActionMap(["OkCancelActions", "ColorActions", "DirectionActions", "MovieSelectionActions"],
268 "left": self.key_left,
269 "right": self.key_right,
271 "down": self.key_down,
272 "showEventInfo": self.StartExif,
275 self["frame"] = MovingPixmap()
276 for x in range(self.thumbsC):
277 self["label"+str(x)] = Label()
278 self["thumb"+str(x)] = Pixmap()
280 self.Thumbnaillist = []
283 self.dirlistcount = 0
291 self.filelist.append((index, framePos, Page, x[0][0], path + x[0][0]))
294 if framePos > (self.thumbsC -1):
298 self.dirlistcount += 1
300 self.maxentry = len(self.filelist)-1
301 self.index = lastindex - self.dirlistcount
305 self.picload = ePicLoad()
306 self.picload.PictureData.get().append(self.showPic)
308 self.onLayoutFinish.append(self.setPicloadConf)
310 self.ThumbTimer = eTimer()
311 self.ThumbTimer.callback.append(self.showPic)
313 def setPicloadConf(self):
314 self.picload.setPara([self["thumb0"].instance.size().width(), self["thumb0"].instance.size().height(), getAspectforPic(), config.pic.cache.value, int(config.pic.resize.value), self.color])
318 def paintFrame(self):
319 #print "index=" + str(self.index)
320 if self.maxentry < self.index or self.index < 0:
323 pos = self.positionlist[self.filelist[self.index][T_FRAME_POS]]
324 self["frame"].moveTo( pos[0], pos[1], 1)
325 self["frame"].startMoving()
327 if self.currPage != self.filelist[self.index][T_PAGE]:
328 self.currPage = self.filelist[self.index][T_PAGE]
332 self.Thumbnaillist = []
333 #clear Labels and Thumbnail
334 for x in range(self.thumbsC):
335 self["label"+str(x)].setText("")
336 self["thumb"+str(x)].hide()
337 #paint Labels and fill Thumbnail-List
338 for x in self.filelist:
339 if x[T_PAGE] == self.currPage:
340 self["label"+str(x[T_FRAME_POS])].setText("(" + str(x[T_INDEX]+1) + ") " + x[T_NAME])
341 self.Thumbnaillist.append([0, x[T_FRAME_POS], x[T_FULL]])
343 #paint Thumbnail start
346 def showPic(self, picInfo=""):
347 for x in range(len(self.Thumbnaillist)):
348 if self.Thumbnaillist[x][0] == 0:
349 if self.picload.getThumbnail(self.Thumbnaillist[x][2]) == 1: #zu tun probier noch mal
350 self.ThumbTimer.start(500, True)
352 self.Thumbnaillist[x][0] = 1
354 elif self.Thumbnaillist[x][0] == 1:
355 self.Thumbnaillist[x][0] = 2
356 ptr = self.picload.getData()
358 self["thumb" + str(self.Thumbnaillist[x][1])].instance.setPixmap(ptr.__deref__())
359 self["thumb" + str(self.Thumbnaillist[x][1])].show()
364 self.index = self.maxentry
369 if self.index > self.maxentry:
374 self.index -= self.thumbsX
376 self.index =self.maxentry
380 self.index += self.thumbsX
381 if self.index > self.maxentry:
386 if self.maxentry < 0:
388 self.session.open(Pic_Exif, self.picload.getInfo(self.filelist[self.index][T_FULL]))
391 if self.maxentry < 0:
393 self.old_index = self.index
394 self.session.openWithCallback(self.callbackView, Pic_Full_View, self.filelist, self.index, self.path)
396 def callbackView(self, val=0):
398 if self.old_index != self.index:
402 self.close(self.index + self.dirlistcount)
404 #---------------------------------------------------------------------------
406 class Pic_Full_View(Screen):
407 def __init__(self, session, filelist, index, path):
409 self.textcolor = config.pic.textcolor.value
410 self.bgcolor = config.pic.bgcolor.value
411 space = config.pic.framesize.value
412 size_w = getDesktop(0).size().width()
413 size_h = getDesktop(0).size().height()
415 self.skin = "<screen position=\"0,0\" size=\"" + str(size_w) + "," + str(size_h) + "\" flags=\"wfNoBorder\" > \
416 <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\" /> \
417 <widget name=\"point\" position=\""+ str(space+5) + "," + str(space+2) + "\" size=\"20,20\" zPosition=\"2\" pixmap=\"skin_default/icons/record.png\" alphatest=\"on\" /> \
418 <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\" /> \
419 <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>"
421 Screen.__init__(self, session)
423 self["actions"] = ActionMap(["OkCancelActions", "ColorActions", "DirectionActions", "MovieSelectionActions"],
426 "green": self.PlayPause,
427 "yellow": self.PlayPause,
428 "blue": self.nextPic,
430 "left": self.prevPic,
431 "right": self.nextPic,
432 "showEventInfo": self.StartExif,
435 self["point"] = Pixmap()
436 self["pic"] = Pixmap()
437 self["play_icon"] = Pixmap()
438 self["file"] = Label(_("please wait, loading picture..."))
442 self.lastindex = index
445 self.dirlistcount = 0
448 if len(filelist[0]) == 3: #orig. filelist
450 self.filelist.append(path + x[0][0])
452 self.dirlistcount += 1
453 else: # thumbnaillist
454 self.filelist.append(x[T_FULL])
456 self.maxentry = len(self.filelist)-1
457 self.index = index - self.dirlistcount
461 self.picload = ePicLoad()
462 self.picload.PictureData.get().append(self.finish_decode)
464 self.slideTimer = eTimer()
465 self.slideTimer.callback.append(self.slidePic)
467 if self.maxentry >= 0:
468 self.onLayoutFinish.append(self.setPicloadConf)
470 def setPicloadConf(self):
471 self.picload.setPara([self["pic"].instance.size().width(), self["pic"].instance.size().height(), getAspectforPic(), 0, int(config.pic.resize.value), self.bgcolor])
473 self["play_icon"].hide()
474 if config.pic.infoline.value == False:
478 def ShowPicture(self):
479 if self.shownow and len(self.currPic):
481 self["file"].setText(self.currPic[0])
482 self.lastindex = self.currPic[1]
483 self["pic"].instance.setPixmap(self.currPic[2].__deref__())
489 def finish_decode(self, picInfo=""):
491 ptr = self.picload.getData()
495 text = picInfo.split('\n',1)
496 text = "(" + str(self.index+1) + "/" + str(self.maxentry+1) + ") " + text[0].split('/')[-1]
500 self.currPic.append(text)
501 self.currPic.append(self.index)
502 self.currPic.append(ptr)
505 def start_decode(self):
506 self.picload.startDecode(self.filelist[self.index])
511 if self.index > self.maxentry:
517 self.index = self.maxentry
520 print "slide to next Picture index=" + str(self.lastindex)
521 if config.pic.loop.value==False and self.lastindex == self.maxentry:
527 if self.slideTimer.isActive():
528 self.slideTimer.stop()
529 self["play_icon"].hide()
531 self.slideTimer.start(config.pic.slidetime.value*1000)
532 self["play_icon"].show()
537 self.index = self.lastindex
547 if self.maxentry < 0:
549 self.session.open(Pic_Exif, self.picload.getInfo(self.filelist[self.lastindex]))
553 self.close(self.lastindex + self.dirlistcount)
555 #------------------------------------------------------------------------------------------
557 def main(session, **kwargs):
558 session.open(picshow)
560 def filescan_open(list, session, **kwargs):
561 # Recreate List as expected by PicView
562 filelist = [((file.path, False), None) for file in list]
563 session.open(Pic_Full_View, filelist, 0, file.path)
565 def filescan(**kwargs):
566 from Components.Scanner import Scanner, ScanPath
568 # Overwrite checkFile to only detect local
569 class LocalScanner(Scanner):
570 def checkFile(self, file):
571 return fileExists(file.path)
574 LocalScanner(mimetypes = ["image/jpeg", "image/png", "image/gif", "image/bmp"],
577 ScanPath(path = "DCIM", with_subdirs = True),
578 ScanPath(path = "", with_subdirs = False),
581 description = "View Photos...",
582 openfnc = filescan_open,
585 def Plugins(**kwargs):
587 [PluginDescriptor(name=_("PicturePlayer"), description=_("fileformats (BMP, PNG, JPG, GIF)"), icon="pictureplayer.png", where = PluginDescriptor.WHERE_PLUGINMENU, fnc=main),
588 PluginDescriptor(name=_("PicturePlayer"), where = PluginDescriptor.WHERE_FILESCAN, fnc = filescan)]