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 else: # thumbnaillist
456 self.filelist.append(x[T_FULL])
458 self.maxentry = len(self.filelist)-1
459 self.index = index - self.dirlistcount
463 self.picload = ePicLoad()
464 self.picload.PictureData.get().append(self.finish_decode)
466 self.slideTimer = eTimer()
467 self.slideTimer.callback.append(self.slidePic)
469 if self.maxentry >= 0:
470 self.onLayoutFinish.append(self.setPicloadConf)
472 def setPicloadConf(self):
474 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])
476 self["play_icon"].hide()
477 if config.pic.infoline.value == False:
481 def ShowPicture(self):
482 if self.shownow and len(self.currPic):
484 self["file"].setText(self.currPic[0])
485 self.lastindex = self.currPic[1]
486 self["pic"].instance.setPixmap(self.currPic[2].__deref__())
492 def finish_decode(self, picInfo=""):
494 ptr = self.picload.getData()
498 text = picInfo.split('\n',1)
499 text = "(" + str(self.index+1) + "/" + str(self.maxentry+1) + ") " + text[0].split('/')[-1]
503 self.currPic.append(text)
504 self.currPic.append(self.index)
505 self.currPic.append(ptr)
508 def start_decode(self):
509 self.picload.startDecode(self.filelist[self.index])
514 if self.index > self.maxentry:
520 self.index = self.maxentry
523 print "slide to next Picture index=" + str(self.lastindex)
524 if config.pic.loop.value==False and self.lastindex == self.maxentry:
530 if self.slideTimer.isActive():
531 self.slideTimer.stop()
532 self["play_icon"].hide()
534 self.slideTimer.start(config.pic.slidetime.value*1000)
535 self["play_icon"].show()
540 self.index = self.lastindex
550 if self.maxentry < 0:
552 self.session.open(Pic_Exif, self.picload.getInfo(self.filelist[self.lastindex]))
556 self.close(self.lastindex + self.dirlistcount)
558 #------------------------------------------------------------------------------------------
560 def main(session, **kwargs):
561 session.open(picshow)
563 def filescan_open(list, session, **kwargs):
564 # Recreate List as expected by PicView
565 filelist = [((file.path, False), None) for file in list]
566 session.open(Pic_Full_View, filelist, 0, file.path)
568 def filescan(**kwargs):
569 from Components.Scanner import Scanner, ScanPath
571 # Overwrite checkFile to only detect local
572 class LocalScanner(Scanner):
573 def checkFile(self, file):
574 return fileExists(file.path)
577 LocalScanner(mimetypes = ["image/jpeg", "image/png", "image/gif", "image/bmp"],
580 ScanPath(path = "DCIM", with_subdirs = True),
581 ScanPath(path = "", with_subdirs = False),
584 description = "View Photos...",
585 openfnc = filescan_open,
588 def Plugins(**kwargs):
590 [PluginDescriptor(name=_("PicturePlayer"), description=_("fileformats (BMP, PNG, JPG, GIF)"), icon="pictureplayer.png", where = PluginDescriptor.WHERE_PLUGINMENU, fnc=main),
591 PluginDescriptor(name=_("PicturePlayer"), where = PluginDescriptor.WHERE_FILESCAN, fnc = filescan)]