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 def __init__(self, session):
150 Screen.__init__(self, session)
151 # for the skin: first try MediaPlayerSettings, then Setup, this allows individual skinning
152 self.skinName = ["PicturePlayerSetup", "Setup" ]
153 self.setup_title = _("Settings")
154 self.onChangedEntry = [ ]
155 self.session = session
157 self["actions"] = ActionMap(["SetupActions"],
159 "cancel": self.keyCancel,
160 "save": self.keySave,
164 self["key_red"] = StaticText(_("Cancel"))
165 self["key_green"] = StaticText(_("OK"))
168 ConfigListScreen.__init__(self, self.list, session = self.session, on_change = self.changedEntry)
170 self.onLayoutFinish.append(self.layoutFinished)
172 def layoutFinished(self):
173 self.setTitle(self.setup_title)
175 def createSetup(self):
177 self.list.append(getConfigListEntry(_("Slideshow Interval (sec.)"), config.pic.slidetime))
178 self.list.append(getConfigListEntry(_("Scaling Mode"), config.pic.resize))
179 self.list.append(getConfigListEntry(_("Cache Thumbnails"), config.pic.cache))
180 self.list.append(getConfigListEntry(_("show Infoline"), config.pic.infoline))
181 self.list.append(getConfigListEntry(_("Frame size in full view"), config.pic.framesize))
182 self.list.append(getConfigListEntry(_("slide picture in loop"), config.pic.loop))
183 self.list.append(getConfigListEntry(_("backgroundcolor"), config.pic.bgcolor))
184 self.list.append(getConfigListEntry(_("textcolor"), config.pic.textcolor))
185 self["config"].list = self.list
186 self["config"].l.setList(self.list)
189 ConfigListScreen.keyLeft(self)
192 ConfigListScreen.keyRight(self)
195 def changedEntry(self):
196 for x in self.onChangedEntry:
199 def getCurrentEntry(self):
200 return self["config"].getCurrent()[0]
202 def getCurrentValue(self):
203 return str(self["config"].getCurrent()[1].getText())
205 def createSummary(self):
206 from Screens.Setup import SetupSummary
209 #---------------------------------------------------------------------------
211 class Pic_Exif(Screen):
213 <screen name="Pic_Exif" position="center,center" size="560,360" title="Info" >
214 <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
215 <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" />
216 <widget source="menu" render="Listbox" position="5,50" size="550,310" scrollbarMode="showOnDemand" selectionDisabled="1" >
217 <convert type="TemplatedMultiContent">
219 "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)],
220 "fonts": [gFont("Regular", 20)],
227 def __init__(self, session, exiflist):
228 Screen.__init__(self, session)
230 self["actions"] = ActionMap(["SetupActions", "ColorActions"],
235 self["key_red"] = StaticText(_("Close"))
237 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:"]
240 for x in range(len(exiflist)):
242 list.append((exifdesc[x], exiflist[x]))
244 name = exiflist[x].split('/')[-1]
245 list.append((exifdesc[x], name))
246 self["menu"] = List(list)
247 self.onLayoutFinish.append(self.layoutFinished)
249 def layoutFinished(self):
250 self.setTitle(_("Info"))
252 #----------------------------------------------------------------------------------------
260 class Pic_Thumb(Screen):
261 def __init__(self, session, piclist, lastindex, path):
263 self.textcolor = config.pic.textcolor.value
264 self.color = config.pic.bgcolor.value
271 size_w = getDesktop(0).size().width()
272 size_h = getDesktop(0).size().height()
273 self.thumbsX = size_w / (self.spaceX + self.picX) # thumbnails in X
274 self.thumbsY = size_h / (self.spaceY + self.picY) # thumbnails in Y
275 self.thumbsC = self.thumbsX * self.thumbsY # all thumbnails
277 self.positionlist = []
281 for x in range(self.thumbsC):
282 posY = x / self.thumbsX
284 if posX >= self.thumbsX:
287 absX = self.spaceX + (posX*(self.spaceX + self.picX))
288 absY = self.spaceY + (posY*(self.spaceY + self.picY))
289 self.positionlist.append((absX, absY))
290 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 + "\" />"
291 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\" />"
293 # Screen, backgroundlabel and MovingPixmap
294 self.skin = "<screen position=\"0,0\" size=\"" + str(size_w) + "," + str(size_h) + "\" flags=\"wfNoBorder\" > \
295 <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>"
297 Screen.__init__(self, session)
299 self["actions"] = ActionMap(["OkCancelActions", "ColorActions", "DirectionActions", "MovieSelectionActions"],
303 "left": self.key_left,
304 "right": self.key_right,
306 "down": self.key_down,
307 "showEventInfo": self.StartExif,
310 self["frame"] = MovingPixmap()
311 for x in range(self.thumbsC):
312 self["label"+str(x)] = StaticText()
313 self["thumb"+str(x)] = Pixmap()
315 self.Thumbnaillist = []
318 self.dirlistcount = 0
326 self.filelist.append((index, framePos, Page, x[0][0], path + x[0][0]))
329 if framePos > (self.thumbsC -1):
333 self.dirlistcount += 1
335 self.maxentry = len(self.filelist)-1
336 self.index = lastindex - self.dirlistcount
340 self.picload = ePicLoad()
341 self.picload.PictureData.get().append(self.showPic)
343 self.onLayoutFinish.append(self.setPicloadConf)
345 self.ThumbTimer = eTimer()
346 self.ThumbTimer.callback.append(self.showPic)
348 def setPicloadConf(self):
350 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])
353 def paintFrame(self):
354 #print "index=" + str(self.index)
355 if self.maxentry < self.index or self.index < 0:
358 pos = self.positionlist[self.filelist[self.index][T_FRAME_POS]]
359 self["frame"].moveTo( pos[0], pos[1], 1)
360 self["frame"].startMoving()
362 if self.currPage != self.filelist[self.index][T_PAGE]:
363 self.currPage = self.filelist[self.index][T_PAGE]
367 self.Thumbnaillist = []
368 #clear Labels and Thumbnail
369 for x in range(self.thumbsC):
370 self["label"+str(x)].setText("")
371 self["thumb"+str(x)].hide()
372 #paint Labels and fill Thumbnail-List
373 for x in self.filelist:
374 if x[T_PAGE] == self.currPage:
375 self["label"+str(x[T_FRAME_POS])].setText("(" + str(x[T_INDEX]+1) + ") " + x[T_NAME])
376 self.Thumbnaillist.append([0, x[T_FRAME_POS], x[T_FULL]])
378 #paint Thumbnail start
381 def showPic(self, picInfo=""):
382 for x in range(len(self.Thumbnaillist)):
383 if self.Thumbnaillist[x][0] == 0:
384 if self.picload.getThumbnail(self.Thumbnaillist[x][2]) == 1: #zu tun probier noch mal
385 self.ThumbTimer.start(500, True)
387 self.Thumbnaillist[x][0] = 1
389 elif self.Thumbnaillist[x][0] == 1:
390 self.Thumbnaillist[x][0] = 2
391 ptr = self.picload.getData()
393 self["thumb" + str(self.Thumbnaillist[x][1])].instance.setPixmap(ptr.__deref__())
394 self["thumb" + str(self.Thumbnaillist[x][1])].show()
399 self.index = self.maxentry
404 if self.index > self.maxentry:
409 self.index -= self.thumbsX
411 self.index =self.maxentry
415 self.index += self.thumbsX
416 if self.index > self.maxentry:
421 if self.maxentry < 0:
423 self.session.open(Pic_Exif, self.picload.getInfo(self.filelist[self.index][T_FULL]))
426 if self.maxentry < 0:
428 self.old_index = self.index
429 self.session.openWithCallback(self.callbackView, Pic_Full_View, self.filelist, self.index, self.path)
431 def callbackView(self, val=0):
433 if self.old_index != self.index:
437 self.close(self.index + self.dirlistcount)
439 #---------------------------------------------------------------------------
441 class Pic_Full_View(Screen):
442 def __init__(self, session, filelist, index, path):
444 self.textcolor = config.pic.textcolor.value
445 self.bgcolor = config.pic.bgcolor.value
446 space = config.pic.framesize.value
447 size_w = getDesktop(0).size().width()
448 size_h = getDesktop(0).size().height()
450 self.skin = "<screen position=\"0,0\" size=\"" + str(size_w) + "," + str(size_h) + "\" flags=\"wfNoBorder\" > \
451 <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\" /> \
452 <widget name=\"point\" position=\""+ str(space+5) + "," + str(space+2) + "\" size=\"20,20\" zPosition=\"2\" pixmap=\"skin_default/icons/record.png\" alphatest=\"on\" /> \
453 <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\" /> \
454 <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>"
456 Screen.__init__(self, session)
458 self["actions"] = ActionMap(["OkCancelActions", "ColorActions", "DirectionActions", "MovieSelectionActions"],
461 "green": self.PlayPause,
462 "yellow": self.PlayPause,
463 "blue": self.nextPic,
465 "left": self.prevPic,
466 "right": self.nextPic,
467 "showEventInfo": self.StartExif,
470 self["point"] = Pixmap()
471 self["pic"] = Pixmap()
472 self["play_icon"] = Pixmap()
473 self["file"] = StaticText(_("please wait, loading picture..."))
477 self.lastindex = index
480 self.dirlistcount = 0
483 if len(filelist[0]) == 3: #orig. filelist
485 self.filelist.append(path + x[0][0])
487 self.dirlistcount += 1
488 elif len(filelist[0]) == 2: #scanlist
490 self.filelist.append(x[0][0])
492 self.dirlistcount += 1
493 else: # thumbnaillist
494 self.filelist.append(x[T_FULL])
496 self.maxentry = len(self.filelist)-1
497 self.index = index - self.dirlistcount
501 self.picload = ePicLoad()
502 self.picload.PictureData.get().append(self.finish_decode)
504 self.slideTimer = eTimer()
505 self.slideTimer.callback.append(self.slidePic)
507 if self.maxentry >= 0:
508 self.onLayoutFinish.append(self.setPicloadConf)
510 def setPicloadConf(self):
512 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])
514 self["play_icon"].hide()
515 if config.pic.infoline.value == False:
516 self["file"].setText("")
519 def ShowPicture(self):
520 if self.shownow and len(self.currPic):
522 self["file"].setText(self.currPic[0])
523 self.lastindex = self.currPic[1]
524 self["pic"].instance.setPixmap(self.currPic[2].__deref__())
530 def finish_decode(self, picInfo=""):
532 ptr = self.picload.getData()
536 text = picInfo.split('\n',1)
537 text = "(" + str(self.index+1) + "/" + str(self.maxentry+1) + ") " + text[0].split('/')[-1]
541 self.currPic.append(text)
542 self.currPic.append(self.index)
543 self.currPic.append(ptr)
546 def start_decode(self):
547 self.picload.startDecode(self.filelist[self.index])
552 if self.index > self.maxentry:
558 self.index = self.maxentry
561 print "slide to next Picture index=" + str(self.lastindex)
562 if config.pic.loop.value==False and self.lastindex == self.maxentry:
568 if self.slideTimer.isActive():
569 self.slideTimer.stop()
570 self["play_icon"].hide()
572 self.slideTimer.start(config.pic.slidetime.value*1000)
573 self["play_icon"].show()
578 self.index = self.lastindex
588 if self.maxentry < 0:
590 self.session.open(Pic_Exif, self.picload.getInfo(self.filelist[self.lastindex]))
594 self.close(self.lastindex + self.dirlistcount)
596 #------------------------------------------------------------------------------------------
598 def main(session, **kwargs):
599 session.open(picshow)
601 def filescan_open(list, session, **kwargs):
602 # Recreate List as expected by PicView
603 filelist = [((file.path, False), None) for file in list]
604 session.open(Pic_Full_View, filelist, 0, file.path)
606 def filescan(**kwargs):
607 from Components.Scanner import Scanner, ScanPath
609 # Overwrite checkFile to only detect local
610 class LocalScanner(Scanner):
611 def checkFile(self, file):
612 return fileExists(file.path)
615 LocalScanner(mimetypes = ["image/jpeg", "image/png", "image/gif", "image/bmp"],
618 ScanPath(path = "DCIM", with_subdirs = True),
619 ScanPath(path = "", with_subdirs = False),
622 description = _("View Photos..."),
623 openfnc = filescan_open,
626 def Plugins(**kwargs):
628 [PluginDescriptor(name=_("PicturePlayer"), description=_("fileformats (BMP, PNG, JPG, GIF)"), icon="pictureplayer.png", where = PluginDescriptor.WHERE_PLUGINMENU, fnc=main),
629 PluginDescriptor(name=_("PicturePlayer"), where = PluginDescriptor.WHERE_FILESCAN, fnc = filescan)]