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
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())
123 #0=Width 1=Height 2=Aspect 3=use_cache 4=resize_type 5=Background(#AARRGGBB)
124 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"))
126 def callbackView(self, val=0):
128 self.filelist.moveToIndex(val)
133 if self.filelist.getCurrentDirectory() is None:
134 config.pic.lastDir.value = "/"
136 config.pic.lastDir.value = self.filelist.getCurrentDirectory()
141 #------------------------------------------------------------------------------------------
143 class Pic_Setup(Screen):
144 def __init__(self, session):
145 self.skin = """<screen position="120,180" size="480,210" title="Settings" >
146 <widget name="liste" position="5,5" size="470,200" />
148 Screen.__init__(self, session)
150 self["actions"] = NumberActionMap(["SetupActions"],
152 "cancel": self.close,
153 "left": self.keyLeft,
154 "right": self.keyRight,
168 self["liste"] = ConfigList(list)
169 list.append(getConfigListEntry(_("Slideshow Interval (sec.)"), config.pic.slidetime))
170 list.append(getConfigListEntry(_("Scaling Mode"), config.pic.resize))
171 list.append(getConfigListEntry(_("Cache Thumbnails"), config.pic.cache))
172 list.append(getConfigListEntry(_("show Infoline"), config.pic.infoline))
173 list.append(getConfigListEntry(_("Frame size in full view"), config.pic.framesize))
174 list.append(getConfigListEntry(_("slide picture in loop"), config.pic.loop))
175 list.append(getConfigListEntry(_("backgroundcolor"), config.pic.bgcolor))
176 list.append(getConfigListEntry(_("textcolor"), config.pic.textcolor))
179 self["liste"].handleKey(KEY_LEFT)
182 self["liste"].handleKey(KEY_RIGHT)
184 def keyNumber(self, number):
185 self["liste"].handleKey(KEY_0 + number)
187 #---------------------------------------------------------------------------
189 class Pic_Exif(Screen):
190 def __init__(self, session, exiflist):
191 self.skin = """<screen position="80,120" size="560,360" title="Info" >
192 <widget source="menu" render="Listbox" position="0,0" size="560,360" scrollbarMode="showOnDemand" selectionDisabled="1" >
193 <convert type="TemplatedMultiContent">
194 {"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 }
198 Screen.__init__(self, session)
200 self["actions"] = ActionMap(["OkCancelActions"],
205 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:"]
208 for x in range(len(exiflist)):
210 list.append((exifdesc[x], exiflist[x]))
212 name = exiflist[x].split('/')[-1]
213 list.append((exifdesc[x], name))
214 self["menu"] = List(list)
216 #----------------------------------------------------------------------------------------
224 class Pic_Thumb(Screen):
225 def __init__(self, session, piclist, lastindex, path):
227 self.textcolor = config.pic.textcolor.value
228 self.color = config.pic.bgcolor.value
235 size_w = getDesktop(0).size().width()
236 size_h = getDesktop(0).size().height()
237 self.thumbsX = size_w / (self.spaceX + self.picX) # thumbnails in X
238 self.thumbsY = size_h / (self.spaceY + self.picY) # thumbnails in Y
239 self.thumbsC = self.thumbsX * self.thumbsY # all thumbnails
241 self.positionlist = []
245 for x in range(self.thumbsC):
246 posY = x / self.thumbsX
248 if posX >= self.thumbsX:
251 absX = self.spaceX + (posX*(self.spaceX + self.picX))
252 absY = self.spaceY + (posY*(self.spaceY + self.picY))
253 self.positionlist.append((absX, absY))
254 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 + "\" />"
256 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\" />"
259 # Screen, backgroundlabel and MovingPixmap
260 self.skin = "<screen position=\"0,0\" size=\"" + str(size_w) + "," + str(size_h) + "\" flags=\"wfNoBorder\" > \
261 <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>"
263 Screen.__init__(self, session)
265 self["actions"] = ActionMap(["OkCancelActions", "ColorActions", "DirectionActions", "MovieSelectionActions"],
269 "left": self.key_left,
270 "right": self.key_right,
272 "down": self.key_down,
273 "showEventInfo": self.StartExif,
276 self["frame"] = MovingPixmap()
277 for x in range(self.thumbsC):
278 self["label"+str(x)] = Label()
279 self["thumb"+str(x)] = Pixmap()
281 self.Thumbnaillist = []
284 self.dirlistcount = 0
292 self.filelist.append((index, framePos, Page, x[0][0], path + x[0][0]))
295 if framePos > (self.thumbsC -1):
299 self.dirlistcount += 1
301 self.maxentry = len(self.filelist)-1
302 self.index = lastindex - self.dirlistcount
306 self.picload = ePicLoad()
307 self.picload.PictureData.get().append(self.showPic)
309 self.onLayoutFinish.append(self.setPicloadConf)
311 self.ThumbTimer = eTimer()
312 self.ThumbTimer.callback.append(self.showPic)
314 def setPicloadConf(self):
316 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])
319 def paintFrame(self):
320 #print "index=" + str(self.index)
321 if self.maxentry < self.index or self.index < 0:
324 pos = self.positionlist[self.filelist[self.index][T_FRAME_POS]]
325 self["frame"].moveTo( pos[0], pos[1], 1)
326 self["frame"].startMoving()
328 if self.currPage != self.filelist[self.index][T_PAGE]:
329 self.currPage = self.filelist[self.index][T_PAGE]
333 self.Thumbnaillist = []
334 #clear Labels and Thumbnail
335 for x in range(self.thumbsC):
336 self["label"+str(x)].setText("")
337 self["thumb"+str(x)].hide()
338 #paint Labels and fill Thumbnail-List
339 for x in self.filelist:
340 if x[T_PAGE] == self.currPage:
341 self["label"+str(x[T_FRAME_POS])].setText("(" + str(x[T_INDEX]+1) + ") " + x[T_NAME])
342 self.Thumbnaillist.append([0, x[T_FRAME_POS], x[T_FULL]])
344 #paint Thumbnail start
347 def showPic(self, picInfo=""):
348 for x in range(len(self.Thumbnaillist)):
349 if self.Thumbnaillist[x][0] == 0:
350 if self.picload.getThumbnail(self.Thumbnaillist[x][2]) == 1: #zu tun probier noch mal
351 self.ThumbTimer.start(500, True)
353 self.Thumbnaillist[x][0] = 1
355 elif self.Thumbnaillist[x][0] == 1:
356 self.Thumbnaillist[x][0] = 2
357 ptr = self.picload.getData()
359 self["thumb" + str(self.Thumbnaillist[x][1])].instance.setPixmap(ptr.__deref__())
360 self["thumb" + str(self.Thumbnaillist[x][1])].show()
365 self.index = self.maxentry
370 if self.index > self.maxentry:
375 self.index -= self.thumbsX
377 self.index =self.maxentry
381 self.index += self.thumbsX
382 if self.index > self.maxentry:
387 if self.maxentry < 0:
389 self.session.open(Pic_Exif, self.picload.getInfo(self.filelist[self.index][T_FULL]))
392 if self.maxentry < 0:
394 self.old_index = self.index
395 self.session.openWithCallback(self.callbackView, Pic_Full_View, self.filelist, self.index, self.path)
397 def callbackView(self, val=0):
399 if self.old_index != self.index:
403 self.close(self.index + self.dirlistcount)
405 #---------------------------------------------------------------------------
407 class Pic_Full_View(Screen):
408 def __init__(self, session, filelist, index, path):
410 self.textcolor = config.pic.textcolor.value
411 self.bgcolor = config.pic.bgcolor.value
412 space = config.pic.framesize.value
413 size_w = getDesktop(0).size().width()
414 size_h = getDesktop(0).size().height()
416 self.skin = "<screen position=\"0,0\" size=\"" + str(size_w) + "," + str(size_h) + "\" flags=\"wfNoBorder\" > \
417 <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\" /> \
418 <widget name=\"point\" position=\""+ str(space+5) + "," + str(space+2) + "\" size=\"20,20\" zPosition=\"2\" pixmap=\"skin_default/icons/record.png\" alphatest=\"on\" /> \
419 <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\" /> \
420 <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>"
422 Screen.__init__(self, session)
424 self["actions"] = ActionMap(["OkCancelActions", "ColorActions", "DirectionActions", "MovieSelectionActions"],
427 "green": self.PlayPause,
428 "yellow": self.PlayPause,
429 "blue": self.nextPic,
431 "left": self.prevPic,
432 "right": self.nextPic,
433 "showEventInfo": self.StartExif,
436 self["point"] = Pixmap()
437 self["pic"] = Pixmap()
438 self["play_icon"] = Pixmap()
439 self["file"] = Label(_("please wait, loading picture..."))
443 self.lastindex = index
446 self.dirlistcount = 0
449 if len(filelist[0]) == 3: #orig. filelist
451 self.filelist.append(path + x[0][0])
453 self.dirlistcount += 1
454 else: # thumbnaillist
455 self.filelist.append(x[T_FULL])
457 self.maxentry = len(self.filelist)-1
458 self.index = index - self.dirlistcount
462 self.picload = ePicLoad()
463 self.picload.PictureData.get().append(self.finish_decode)
465 self.slideTimer = eTimer()
466 self.slideTimer.callback.append(self.slidePic)
468 if self.maxentry >= 0:
469 self.onLayoutFinish.append(self.setPicloadConf)
471 def setPicloadConf(self):
473 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])
475 self["play_icon"].hide()
476 if config.pic.infoline.value == False:
480 def ShowPicture(self):
481 if self.shownow and len(self.currPic):
483 self["file"].setText(self.currPic[0])
484 self.lastindex = self.currPic[1]
485 self["pic"].instance.setPixmap(self.currPic[2].__deref__())
491 def finish_decode(self, picInfo=""):
493 ptr = self.picload.getData()
497 text = picInfo.split('\n',1)
498 text = "(" + str(self.index+1) + "/" + str(self.maxentry+1) + ") " + text[0].split('/')[-1]
502 self.currPic.append(text)
503 self.currPic.append(self.index)
504 self.currPic.append(ptr)
507 def start_decode(self):
508 self.picload.startDecode(self.filelist[self.index])
513 if self.index > self.maxentry:
519 self.index = self.maxentry
522 print "slide to next Picture index=" + str(self.lastindex)
523 if config.pic.loop.value==False and self.lastindex == self.maxentry:
529 if self.slideTimer.isActive():
530 self.slideTimer.stop()
531 self["play_icon"].hide()
533 self.slideTimer.start(config.pic.slidetime.value*1000)
534 self["play_icon"].show()
539 self.index = self.lastindex
549 if self.maxentry < 0:
551 self.session.open(Pic_Exif, self.picload.getInfo(self.filelist[self.lastindex]))
555 self.close(self.lastindex + self.dirlistcount)
557 #------------------------------------------------------------------------------------------
559 def main(session, **kwargs):
560 session.open(picshow)
562 def filescan_open(list, session, **kwargs):
563 # Recreate List as expected by PicView
564 filelist = [((file.path, False), None) for file in list]
565 session.open(Pic_Full_View, filelist, 0, file.path)
567 def filescan(**kwargs):
568 from Components.Scanner import Scanner, ScanPath
570 # Overwrite checkFile to only detect local
571 class LocalScanner(Scanner):
572 def checkFile(self, file):
573 return fileExists(file.path)
576 LocalScanner(mimetypes = ["image/jpeg", "image/png", "image/gif", "image/bmp"],
579 ScanPath(path = "DCIM", with_subdirs = True),
580 ScanPath(path = "", with_subdirs = False),
583 description = "View Photos...",
584 openfnc = filescan_open,
587 def Plugins(**kwargs):
589 [PluginDescriptor(name=_("PicturePlayer"), description=_("fileformats (BMP, PNG, JPG, GIF)"), icon="pictureplayer.png", where = PluginDescriptor.WHERE_PLUGINMENU, fnc=main),
590 PluginDescriptor(name=_("PicturePlayer"), where = PluginDescriptor.WHERE_FILESCAN, fnc = filescan)]