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.Sources.StaticText import StaticText
10 from Components.FileList import FileList
11 from Components.AVSwitch import AVSwitch
12 from Components.Sources.List import List
13 from Components.ConfigList import ConfigList, ConfigListScreen
15 from Components.config import config, ConfigSubsection, ConfigInteger, ConfigSelection, ConfigText, ConfigEnableDisable, KEY_LEFT, KEY_RIGHT, KEY_0, getConfigListEntry
18 return AVSwitch().getFramebufferScale()
20 config.pic = ConfigSubsection()
21 config.pic.framesize = ConfigInteger(default=30, limits=(5, 99))
22 config.pic.slidetime = ConfigInteger(default=10, limits=(10, 60))
23 config.pic.resize = ConfigSelection(default="1", choices = [("0", _("simple")), ("1", _("better"))])
24 config.pic.cache = ConfigEnableDisable(default=True)
25 config.pic.lastDir = ConfigText(default=resolveFilename(SCOPE_MEDIA))
26 config.pic.infoline = ConfigEnableDisable(default=True)
27 config.pic.loop = ConfigEnableDisable(default=True)
28 config.pic.bgcolor = ConfigSelection(default="#00000000", choices = [("#00000000", _("black")),("#009eb9ff", _("blue")),("#00ff5a51", _("red")), ("#00ffe875", _("yellow")), ("#0038FF48", _("green"))])
29 config.pic.textcolor = ConfigSelection(default="#0038FF48", choices = [("#00000000", _("black")),("#009eb9ff", _("blue")),("#00ff5a51", _("red")), ("#00ffe875", _("yellow")), ("#0038FF48", _("green"))])
31 class picshow(Screen):
33 <screen name="picshow" position="center,center" size="560,440" title="PicturePlayer" >
34 <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
35 <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
36 <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" size="140,40" alphatest="on" />
37 <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" size="140,40" alphatest="on" />
38 <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" />
39 <widget source="key_green" render="Label" position="140,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" transparent="1" />
40 <widget source="key_yellow" render="Label" position="280,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#a08500" transparent="1" />
41 <widget source="key_blue" render="Label" position="420,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#18188b" transparent="1" />
42 <widget source="label" render="Label" position="5,55" size="350,140" font="Regular;19" backgroundColor="#25062748" transparent="1" />
43 <widget name="thn" position="360,40" size="180,160" alphatest="on" />
44 <widget name="filelist" position="5,205" zPosition="2" size="550,230" scrollbarMode="showOnDemand" />
47 def __init__(self, session):
48 Screen.__init__(self, session)
50 self["actions"] = ActionMap(["OkCancelActions", "ColorActions", "DirectionActions"],
52 "cancel": self.KeyExit,
54 "green": self.KeyGreen,
55 "yellow": self.KeyYellow,
60 self["key_red"] = StaticText(_("Close"))
61 self["key_green"] = StaticText(_("Thumbnails"))
62 self["key_yellow"] = StaticText("")
63 self["key_blue"] = StaticText(_("Setup"))
64 self["label"] = StaticText("")
65 self["thn"] = Pixmap()
67 currDir = config.pic.lastDir.value
68 if not pathExists(currDir):
71 self.filelist = FileList(currDir, matchingPattern = "(?i)^.*\.(jpeg|jpg|jpe|png|bmp|gif)")
72 self["filelist"] = self.filelist
73 self["filelist"].onSelectionChanged.append(self.selectionChanged)
75 self.ThumbTimer = eTimer()
76 self.ThumbTimer.callback.append(self.showThumb)
78 self.picload = ePicLoad()
79 self.picload.PictureData.get().append(self.showPic)
81 self.onLayoutFinish.append(self.setConf)
83 def showPic(self, picInfo=""):
84 ptr = self.picload.getData()
86 self["thn"].instance.setPixmap(ptr.__deref__())
89 text = picInfo.split('\n',1)
90 self["label"].setText(text[1])
91 self["key_yellow"].setText(_("Exif"))
94 if not self.filelist.canDescent():
95 if self.filelist.getCurrentDirectory() and self.filelist.getFilename():
96 if self.picload.getThumbnail(self.filelist.getCurrentDirectory() + self.filelist.getFilename()) == 1:
97 self.ThumbTimer.start(500, True)
99 def selectionChanged(self):
100 if not self.filelist.canDescent():
101 self.ThumbTimer.start(500, True)
103 self["label"].setText("")
105 self["key_yellow"].setText("")
108 #if not self.filelist.canDescent():
109 self.session.openWithCallback(self.callbackView, Pic_Thumb, self.filelist.getFileList(), self.filelist.getSelectionIndex(), self.filelist.getCurrentDirectory())
112 if not self.filelist.canDescent():
113 self.session.open(Pic_Exif, self.picload.getInfo(self.filelist.getCurrentDirectory() + self.filelist.getFilename()))
116 self.session.openWithCallback(self.setConf ,Pic_Setup)
119 if self.filelist.canDescent():
120 self.filelist.descent()
122 self.session.openWithCallback(self.callbackView, Pic_Full_View, self.filelist.getFileList(), self.filelist.getSelectionIndex(), self.filelist.getCurrentDirectory())
125 self.setTitle(_("PicturePlayer"))
127 #0=Width 1=Height 2=Aspect 3=use_cache 4=resize_type 5=Background(#AARRGGBB)
128 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"))
130 def callbackView(self, val=0):
132 self.filelist.moveToIndex(val)
137 if self.filelist.getCurrentDirectory() is None:
138 config.pic.lastDir.value = "/"
140 config.pic.lastDir.value = self.filelist.getCurrentDirectory()
146 class Pic_Setup(Screen, ConfigListScreen):
148 <screen name="Pic_Setup" position="center,center" size="550,350" title="Settings" >
149 <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
150 <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
151 <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" />
152 <widget source="key_green" render="Label" position="140,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" transparent="1" />
153 <widget name="config" position="5,50" size="540,300" />
155 def __init__(self, session):
156 Screen.__init__(self, session)
157 self.session = session
159 self["actions"] = ActionMap(["SetupActions", "ColorActions"],
161 "cancel": self.keyCancel,
162 "save": self.keySave,
165 self["key_red"] = StaticText(_("Cancel"))
166 self["key_green"] = StaticText(_("OK"))
169 ConfigListScreen.__init__(self, self.list, session = self.session)
171 self.onLayoutFinish.append(self.layoutFinished)
173 def layoutFinished(self):
174 self.setTitle(_("Settings"))
176 def createSetup(self):
178 self.list.append(getConfigListEntry(_("Slideshow Interval (sec.)"), config.pic.slidetime))
179 self.list.append(getConfigListEntry(_("Scaling Mode"), config.pic.resize))
180 self.list.append(getConfigListEntry(_("Cache Thumbnails"), config.pic.cache))
181 self.list.append(getConfigListEntry(_("show Infoline"), config.pic.infoline))
182 self.list.append(getConfigListEntry(_("Frame size in full view"), config.pic.framesize))
183 self.list.append(getConfigListEntry(_("slide picture in loop"), config.pic.loop))
184 self.list.append(getConfigListEntry(_("backgroundcolor"), config.pic.bgcolor))
185 self.list.append(getConfigListEntry(_("textcolor"), config.pic.textcolor))
186 self["config"].list = self.list
187 self["config"].l.setList(self.list)
190 ConfigListScreen.keyLeft(self)
193 ConfigListScreen.keyRight(self)
196 class Pic_Exif(Screen):
198 <screen name="Pic_Exif" position="center,center" size="560,360" title="Info" >
199 <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
200 <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" />
201 <widget source="menu" render="Listbox" position="5,50" size="550,310" scrollbarMode="showOnDemand" selectionDisabled="1" >
202 <convert type="TemplatedMultiContent">
204 "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)],
205 "fonts": [gFont("Regular", 20)],
212 def __init__(self, session, exiflist):
213 Screen.__init__(self, session)
215 self["actions"] = ActionMap(["OkCancelActions"],
220 self["key_red"] = StaticText(_("Close"))
222 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:"]
225 for x in range(len(exiflist)):
227 list.append((exifdesc[x], exiflist[x]))
229 name = exiflist[x].split('/')[-1]
230 list.append((exifdesc[x], name))
231 self["menu"] = List(list)
232 self.onLayoutFinish.append(self.layoutFinished)
234 def layoutFinished(self):
235 self.setTitle(_("Info"))
244 class Pic_Thumb(Screen):
245 def __init__(self, session, piclist, lastindex, path):
247 self.textcolor = config.pic.textcolor.value
248 self.color = config.pic.bgcolor.value
255 size_w = getDesktop(0).size().width()
256 size_h = getDesktop(0).size().height()
257 self.thumbsX = size_w / (self.spaceX + self.picX) # thumbnails in X
258 self.thumbsY = size_h / (self.spaceY + self.picY) # thumbnails in Y
259 self.thumbsC = self.thumbsX * self.thumbsY # all thumbnails
261 self.positionlist = []
265 for x in range(self.thumbsC):
266 posY = x / self.thumbsX
268 if posX >= self.thumbsX:
271 absX = self.spaceX + (posX*(self.spaceX + self.picX))
272 absY = self.spaceY + (posY*(self.spaceY + self.picY))
273 self.positionlist.append((absX, absY))
274 skincontent += "<widget source=\"label" + str(x) + "\" render=\"Label\" 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 + "\" />"
276 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\" />"
279 # Screen, backgroundlabel and MovingPixmap
280 self.skin = "<screen position=\"0,0\" size=\"" + str(size_w) + "," + str(size_h) + "\" flags=\"wfNoBorder\" > \
281 <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>"
283 Screen.__init__(self, session)
285 self["actions"] = ActionMap(["OkCancelActions", "ColorActions", "DirectionActions", "MovieSelectionActions"],
289 "left": self.key_left,
290 "right": self.key_right,
292 "down": self.key_down,
293 "showEventInfo": self.StartExif,
296 self["frame"] = MovingPixmap()
297 for x in range(self.thumbsC):
298 self["label"+str(x)] = StaticText()
299 self["thumb"+str(x)] = Pixmap()
301 self.Thumbnaillist = []
304 self.dirlistcount = 0
312 self.filelist.append((index, framePos, Page, x[0][0], path + x[0][0]))
315 if framePos > (self.thumbsC -1):
319 self.dirlistcount += 1
321 self.maxentry = len(self.filelist)-1
322 self.index = lastindex - self.dirlistcount
326 self.picload = ePicLoad()
327 self.picload.PictureData.get().append(self.showPic)
329 self.onLayoutFinish.append(self.setPicloadConf)
331 self.ThumbTimer = eTimer()
332 self.ThumbTimer.callback.append(self.showPic)
334 def setPicloadConf(self):
336 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])
339 def paintFrame(self):
340 #print "index=" + str(self.index)
341 if self.maxentry < self.index or self.index < 0:
344 pos = self.positionlist[self.filelist[self.index][T_FRAME_POS]]
345 self["frame"].moveTo( pos[0], pos[1], 1)
346 self["frame"].startMoving()
348 if self.currPage != self.filelist[self.index][T_PAGE]:
349 self.currPage = self.filelist[self.index][T_PAGE]
353 self.Thumbnaillist = []
354 #clear Labels and Thumbnail
355 for x in range(self.thumbsC):
356 self["label"+str(x)].setText("")
357 self["thumb"+str(x)].hide()
358 #paint Labels and fill Thumbnail-List
359 for x in self.filelist:
360 if x[T_PAGE] == self.currPage:
361 self["label"+str(x[T_FRAME_POS])].setText("(" + str(x[T_INDEX]+1) + ") " + x[T_NAME])
362 self.Thumbnaillist.append([0, x[T_FRAME_POS], x[T_FULL]])
364 #paint Thumbnail start
367 def showPic(self, picInfo=""):
368 for x in range(len(self.Thumbnaillist)):
369 if self.Thumbnaillist[x][0] == 0:
370 if self.picload.getThumbnail(self.Thumbnaillist[x][2]) == 1: #zu tun probier noch mal
371 self.ThumbTimer.start(500, True)
373 self.Thumbnaillist[x][0] = 1
375 elif self.Thumbnaillist[x][0] == 1:
376 self.Thumbnaillist[x][0] = 2
377 ptr = self.picload.getData()
379 self["thumb" + str(self.Thumbnaillist[x][1])].instance.setPixmap(ptr.__deref__())
380 self["thumb" + str(self.Thumbnaillist[x][1])].show()
385 self.index = self.maxentry
390 if self.index > self.maxentry:
395 self.index -= self.thumbsX
397 self.index =self.maxentry
401 self.index += self.thumbsX
402 if self.index > self.maxentry:
407 if self.maxentry < 0:
409 self.session.open(Pic_Exif, self.picload.getInfo(self.filelist[self.index][T_FULL]))
412 if self.maxentry < 0:
414 self.old_index = self.index
415 self.session.openWithCallback(self.callbackView, Pic_Full_View, self.filelist, self.index, self.path)
417 def callbackView(self, val=0):
419 if self.old_index != self.index:
423 self.close(self.index + self.dirlistcount)
425 #---------------------------------------------------------------------------
427 class Pic_Full_View(Screen):
428 def __init__(self, session, filelist, index, path):
430 self.textcolor = config.pic.textcolor.value
431 self.bgcolor = config.pic.bgcolor.value
432 space = config.pic.framesize.value
433 size_w = getDesktop(0).size().width()
434 size_h = getDesktop(0).size().height()
436 self.skin = "<screen position=\"0,0\" size=\"" + str(size_w) + "," + str(size_h) + "\" flags=\"wfNoBorder\" > \
437 <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\" /> \
438 <widget name=\"point\" position=\""+ str(space+5) + "," + str(space+2) + "\" size=\"20,20\" zPosition=\"2\" pixmap=\"skin_default/icons/record.png\" alphatest=\"on\" /> \
439 <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\" /> \
440 <widget source=\"file\" render=\"Label\" 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>"
442 Screen.__init__(self, session)
444 self["actions"] = ActionMap(["OkCancelActions", "ColorActions", "DirectionActions", "MovieSelectionActions"],
447 "green": self.PlayPause,
448 "yellow": self.PlayPause,
449 "blue": self.nextPic,
451 "left": self.prevPic,
452 "right": self.nextPic,
453 "showEventInfo": self.StartExif,
456 self["point"] = Pixmap()
457 self["pic"] = Pixmap()
458 self["play_icon"] = Pixmap()
459 self["file"] = StaticText(_("please wait, loading picture..."))
463 self.lastindex = index
466 self.dirlistcount = 0
469 if len(filelist[0]) == 3: #orig. filelist
471 self.filelist.append(path + x[0][0])
473 self.dirlistcount += 1
474 elif len(filelist[0]) == 2: #scanlist
476 self.filelist.append(x[0][0])
478 self.dirlistcount += 1
479 else: # thumbnaillist
480 self.filelist.append(x[T_FULL])
482 self.maxentry = len(self.filelist)-1
483 self.index = index - self.dirlistcount
487 self.picload = ePicLoad()
488 self.picload.PictureData.get().append(self.finish_decode)
490 self.slideTimer = eTimer()
491 self.slideTimer.callback.append(self.slidePic)
493 if self.maxentry >= 0:
494 self.onLayoutFinish.append(self.setPicloadConf)
496 def setPicloadConf(self):
498 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])
500 self["play_icon"].hide()
501 if config.pic.infoline.value == False:
502 self["file"].setText("")
505 def ShowPicture(self):
506 if self.shownow and len(self.currPic):
508 self["file"].setText(self.currPic[0])
509 self.lastindex = self.currPic[1]
510 self["pic"].instance.setPixmap(self.currPic[2].__deref__())
516 def finish_decode(self, picInfo=""):
518 ptr = self.picload.getData()
522 text = picInfo.split('\n',1)
523 text = "(" + str(self.index+1) + "/" + str(self.maxentry+1) + ") " + text[0].split('/')[-1]
527 self.currPic.append(text)
528 self.currPic.append(self.index)
529 self.currPic.append(ptr)
532 def start_decode(self):
533 self.picload.startDecode(self.filelist[self.index])
538 if self.index > self.maxentry:
544 self.index = self.maxentry
547 print "slide to next Picture index=" + str(self.lastindex)
548 if config.pic.loop.value==False and self.lastindex == self.maxentry:
554 if self.slideTimer.isActive():
555 self.slideTimer.stop()
556 self["play_icon"].hide()
558 self.slideTimer.start(config.pic.slidetime.value*1000)
559 self["play_icon"].show()
564 self.index = self.lastindex
574 if self.maxentry < 0:
576 self.session.open(Pic_Exif, self.picload.getInfo(self.filelist[self.lastindex]))
580 self.close(self.lastindex + self.dirlistcount)
582 #------------------------------------------------------------------------------------------
584 def main(session, **kwargs):
585 session.open(picshow)
587 def filescan_open(list, session, **kwargs):
588 # Recreate List as expected by PicView
589 filelist = [((file.path, False), None) for file in list]
590 session.open(Pic_Full_View, filelist, 0, file.path)
592 def filescan(**kwargs):
593 from Components.Scanner import Scanner, ScanPath
595 # Overwrite checkFile to only detect local
596 class LocalScanner(Scanner):
597 def checkFile(self, file):
598 return fileExists(file.path)
601 LocalScanner(mimetypes = ["image/jpeg", "image/png", "image/gif", "image/bmp"],
604 ScanPath(path = "DCIM", with_subdirs = True),
605 ScanPath(path = "", with_subdirs = False),
608 description = _("View Photos..."),
609 openfnc = filescan_open,
612 def Plugins(**kwargs):
614 [PluginDescriptor(name=_("PicturePlayer"), description=_("fileformats (BMP, PNG, JPG, GIF)"), icon="pictureplayer.png", where = PluginDescriptor.WHERE_PLUGINMENU, fnc=main),
615 PluginDescriptor(name=_("PicturePlayer"), where = PluginDescriptor.WHERE_FILESCAN, fnc = filescan)]