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()
145 #------------------------------------------------------------------------------------------
147 class Pic_Setup(Screen, ConfigListScreen):
149 <screen name="Pic_Setup" position="center,center" size="550,350" title="Settings" >
150 <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
151 <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
152 <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" />
153 <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" />
154 <widget name="config" position="5,50" size="540,300" />
156 def __init__(self, session):
157 Screen.__init__(self, session)
158 self.session = session
160 self["actions"] = ActionMap(["SetupActions", "ColorActions"],
162 "cancel": self.keyCancel,
163 "save": self.keySave,
166 self["key_red"] = StaticText(_("Cancel"))
167 self["key_green"] = StaticText(_("OK"))
170 ConfigListScreen.__init__(self, self.list, session = self.session)
172 self.onLayoutFinish.append(self.layoutFinished)
174 def layoutFinished(self):
175 self.setTitle(_("Settings"))
177 def createSetup(self):
179 self.list.append(getConfigListEntry(_("Slideshow Interval (sec.)"), config.pic.slidetime))
180 self.list.append(getConfigListEntry(_("Scaling Mode"), config.pic.resize))
181 self.list.append(getConfigListEntry(_("Cache Thumbnails"), config.pic.cache))
182 self.list.append(getConfigListEntry(_("show Infoline"), config.pic.infoline))
183 self.list.append(getConfigListEntry(_("Frame size in full view"), config.pic.framesize))
184 self.list.append(getConfigListEntry(_("slide picture in loop"), config.pic.loop))
185 self.list.append(getConfigListEntry(_("backgroundcolor"), config.pic.bgcolor))
186 self.list.append(getConfigListEntry(_("textcolor"), config.pic.textcolor))
187 self["config"].list = self.list
188 self["config"].l.setList(self.list)
191 ConfigListScreen.keyLeft(self)
194 ConfigListScreen.keyRight(self)
196 #---------------------------------------------------------------------------
198 class Pic_Exif(Screen):
200 <screen name="Pic_Exif" position="center,center" size="560,360" title="Info" >
201 <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
202 <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" />
203 <widget source="menu" render="Listbox" position="5,50" size="550,310" scrollbarMode="showOnDemand" selectionDisabled="1" >
204 <convert type="TemplatedMultiContent">
206 "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)],
207 "fonts": [gFont("Regular", 20)],
214 def __init__(self, session, exiflist):
215 Screen.__init__(self, session)
217 self["actions"] = ActionMap(["SetupActions", "ColorActions"],
222 self["key_red"] = StaticText(_("Close"))
224 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:"]
227 for x in range(len(exiflist)):
229 list.append((exifdesc[x], exiflist[x]))
231 name = exiflist[x].split('/')[-1]
232 list.append((exifdesc[x], name))
233 self["menu"] = List(list)
234 self.onLayoutFinish.append(self.layoutFinished)
236 def layoutFinished(self):
237 self.setTitle(_("Info"))
239 #----------------------------------------------------------------------------------------
247 class Pic_Thumb(Screen):
248 def __init__(self, session, piclist, lastindex, path):
250 self.textcolor = config.pic.textcolor.value
251 self.color = config.pic.bgcolor.value
258 size_w = getDesktop(0).size().width()
259 size_h = getDesktop(0).size().height()
260 self.thumbsX = size_w / (self.spaceX + self.picX) # thumbnails in X
261 self.thumbsY = size_h / (self.spaceY + self.picY) # thumbnails in Y
262 self.thumbsC = self.thumbsX * self.thumbsY # all thumbnails
264 self.positionlist = []
268 for x in range(self.thumbsC):
269 posY = x / self.thumbsX
271 if posX >= self.thumbsX:
274 absX = self.spaceX + (posX*(self.spaceX + self.picX))
275 absY = self.spaceY + (posY*(self.spaceY + self.picY))
276 self.positionlist.append((absX, absY))
277 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 + "\" />"
278 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\" />"
280 # Screen, backgroundlabel and MovingPixmap
281 self.skin = "<screen position=\"0,0\" size=\"" + str(size_w) + "," + str(size_h) + "\" flags=\"wfNoBorder\" > \
282 <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>"
284 Screen.__init__(self, session)
286 self["actions"] = ActionMap(["OkCancelActions", "ColorActions", "DirectionActions", "MovieSelectionActions"],
290 "left": self.key_left,
291 "right": self.key_right,
293 "down": self.key_down,
294 "showEventInfo": self.StartExif,
297 self["frame"] = MovingPixmap()
298 for x in range(self.thumbsC):
299 self["label"+str(x)] = StaticText()
300 self["thumb"+str(x)] = Pixmap()
302 self.Thumbnaillist = []
305 self.dirlistcount = 0
313 self.filelist.append((index, framePos, Page, x[0][0], path + x[0][0]))
316 if framePos > (self.thumbsC -1):
320 self.dirlistcount += 1
322 self.maxentry = len(self.filelist)-1
323 self.index = lastindex - self.dirlistcount
327 self.picload = ePicLoad()
328 self.picload.PictureData.get().append(self.showPic)
330 self.onLayoutFinish.append(self.setPicloadConf)
332 self.ThumbTimer = eTimer()
333 self.ThumbTimer.callback.append(self.showPic)
335 def setPicloadConf(self):
337 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])
340 def paintFrame(self):
341 #print "index=" + str(self.index)
342 if self.maxentry < self.index or self.index < 0:
345 pos = self.positionlist[self.filelist[self.index][T_FRAME_POS]]
346 self["frame"].moveTo( pos[0], pos[1], 1)
347 self["frame"].startMoving()
349 if self.currPage != self.filelist[self.index][T_PAGE]:
350 self.currPage = self.filelist[self.index][T_PAGE]
354 self.Thumbnaillist = []
355 #clear Labels and Thumbnail
356 for x in range(self.thumbsC):
357 self["label"+str(x)].setText("")
358 self["thumb"+str(x)].hide()
359 #paint Labels and fill Thumbnail-List
360 for x in self.filelist:
361 if x[T_PAGE] == self.currPage:
362 self["label"+str(x[T_FRAME_POS])].setText("(" + str(x[T_INDEX]+1) + ") " + x[T_NAME])
363 self.Thumbnaillist.append([0, x[T_FRAME_POS], x[T_FULL]])
365 #paint Thumbnail start
368 def showPic(self, picInfo=""):
369 for x in range(len(self.Thumbnaillist)):
370 if self.Thumbnaillist[x][0] == 0:
371 if self.picload.getThumbnail(self.Thumbnaillist[x][2]) == 1: #zu tun probier noch mal
372 self.ThumbTimer.start(500, True)
374 self.Thumbnaillist[x][0] = 1
376 elif self.Thumbnaillist[x][0] == 1:
377 self.Thumbnaillist[x][0] = 2
378 ptr = self.picload.getData()
380 self["thumb" + str(self.Thumbnaillist[x][1])].instance.setPixmap(ptr.__deref__())
381 self["thumb" + str(self.Thumbnaillist[x][1])].show()
386 self.index = self.maxentry
391 if self.index > self.maxentry:
396 self.index -= self.thumbsX
398 self.index =self.maxentry
402 self.index += self.thumbsX
403 if self.index > self.maxentry:
408 if self.maxentry < 0:
410 self.session.open(Pic_Exif, self.picload.getInfo(self.filelist[self.index][T_FULL]))
413 if self.maxentry < 0:
415 self.old_index = self.index
416 self.session.openWithCallback(self.callbackView, Pic_Full_View, self.filelist, self.index, self.path)
418 def callbackView(self, val=0):
420 if self.old_index != self.index:
424 self.close(self.index + self.dirlistcount)
426 #---------------------------------------------------------------------------
428 class Pic_Full_View(Screen):
429 def __init__(self, session, filelist, index, path):
431 self.textcolor = config.pic.textcolor.value
432 self.bgcolor = config.pic.bgcolor.value
433 space = config.pic.framesize.value
434 size_w = getDesktop(0).size().width()
435 size_h = getDesktop(0).size().height()
437 self.skin = "<screen position=\"0,0\" size=\"" + str(size_w) + "," + str(size_h) + "\" flags=\"wfNoBorder\" > \
438 <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\" /> \
439 <widget name=\"point\" position=\""+ str(space+5) + "," + str(space+2) + "\" size=\"20,20\" zPosition=\"2\" pixmap=\"skin_default/icons/record.png\" alphatest=\"on\" /> \
440 <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\" /> \
441 <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>"
443 Screen.__init__(self, session)
445 self["actions"] = ActionMap(["OkCancelActions", "ColorActions", "DirectionActions", "MovieSelectionActions"],
448 "green": self.PlayPause,
449 "yellow": self.PlayPause,
450 "blue": self.nextPic,
452 "left": self.prevPic,
453 "right": self.nextPic,
454 "showEventInfo": self.StartExif,
457 self["point"] = Pixmap()
458 self["pic"] = Pixmap()
459 self["play_icon"] = Pixmap()
460 self["file"] = StaticText(_("please wait, loading picture..."))
464 self.lastindex = index
467 self.dirlistcount = 0
470 if len(filelist[0]) == 3: #orig. filelist
472 self.filelist.append(path + x[0][0])
474 self.dirlistcount += 1
475 elif len(filelist[0]) == 2: #scanlist
477 self.filelist.append(x[0][0])
479 self.dirlistcount += 1
480 else: # thumbnaillist
481 self.filelist.append(x[T_FULL])
483 self.maxentry = len(self.filelist)-1
484 self.index = index - self.dirlistcount
488 self.picload = ePicLoad()
489 self.picload.PictureData.get().append(self.finish_decode)
491 self.slideTimer = eTimer()
492 self.slideTimer.callback.append(self.slidePic)
494 if self.maxentry >= 0:
495 self.onLayoutFinish.append(self.setPicloadConf)
497 def setPicloadConf(self):
499 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])
501 self["play_icon"].hide()
502 if config.pic.infoline.value == False:
503 self["file"].setText("")
506 def ShowPicture(self):
507 if self.shownow and len(self.currPic):
509 self["file"].setText(self.currPic[0])
510 self.lastindex = self.currPic[1]
511 self["pic"].instance.setPixmap(self.currPic[2].__deref__())
517 def finish_decode(self, picInfo=""):
519 ptr = self.picload.getData()
523 text = picInfo.split('\n',1)
524 text = "(" + str(self.index+1) + "/" + str(self.maxentry+1) + ") " + text[0].split('/')[-1]
528 self.currPic.append(text)
529 self.currPic.append(self.index)
530 self.currPic.append(ptr)
533 def start_decode(self):
534 self.picload.startDecode(self.filelist[self.index])
539 if self.index > self.maxentry:
545 self.index = self.maxentry
548 print "slide to next Picture index=" + str(self.lastindex)
549 if config.pic.loop.value==False and self.lastindex == self.maxentry:
555 if self.slideTimer.isActive():
556 self.slideTimer.stop()
557 self["play_icon"].hide()
559 self.slideTimer.start(config.pic.slidetime.value*1000)
560 self["play_icon"].show()
565 self.index = self.lastindex
575 if self.maxentry < 0:
577 self.session.open(Pic_Exif, self.picload.getInfo(self.filelist[self.lastindex]))
581 self.close(self.lastindex + self.dirlistcount)
583 #------------------------------------------------------------------------------------------
585 def main(session, **kwargs):
586 session.open(picshow)
588 def filescan_open(list, session, **kwargs):
589 # Recreate List as expected by PicView
590 filelist = [((file.path, False), None) for file in list]
591 session.open(Pic_Full_View, filelist, 0, file.path)
593 def filescan(**kwargs):
594 from Components.Scanner import Scanner, ScanPath
596 # Overwrite checkFile to only detect local
597 class LocalScanner(Scanner):
598 def checkFile(self, file):
599 return fileExists(file.path)
602 LocalScanner(mimetypes = ["image/jpeg", "image/png", "image/gif", "image/bmp"],
605 ScanPath(path = "DCIM", with_subdirs = True),
606 ScanPath(path = "", with_subdirs = False),
609 description = _("View Photos..."),
610 openfnc = filescan_open,
613 def Plugins(**kwargs):
615 [PluginDescriptor(name=_("PicturePlayer"), description=_("fileformats (BMP, PNG, JPG, GIF)"), icon="pictureplayer.png", where = PluginDescriptor.WHERE_PLUGINMENU, fnc=main),
616 PluginDescriptor(name=_("PicturePlayer"), where = PluginDescriptor.WHERE_FILESCAN, fnc = filescan)]