1 from enigma import eListbox
2 from enigma import eListboxPythonMultiContent
3 from enigma import ePicLoad
4 from enigma import loadPNG
5 from enigma import gFont
7 from Screens.Screen import Screen
8 from Screens.MessageBox import MessageBox
9 from Screens.InputBox import InputBox
10 from Screens.ChoiceBox import ChoiceBox
11 from Components.ActionMap import ActionMap
12 from Components.Label import Label
13 from Components.MenuList import MenuList
14 from Components.FileList import EXTENSIONS
16 from Components.config import config, ConfigSubsection,ConfigSelection,ConfigText,ConfigYesNo
18 from Components.Input import Input
19 from Components.Pixmap import Pixmap
20 from Plugins.Plugin import PluginDescriptor
23 from re import compile
25 from pyexpat import ExpatError
26 import xml.dom.minidom
29 from WebcamViewConfig import WebcamViewerMenu
30 from PictureScreen import PictureScreen
31 from WebcamTravel import TravelWebcamviewer
33 myname = "Webcam/Picture Viewer"
36 config.plugins.pictureviewer = ConfigSubsection()
37 config.plugins.pictureviewer.slideshowtime = ConfigSelection(default="5000", choices = [("5000", _("5 Sekunden")), ("10000", _("10 Sekunden")), ("20000", _("20 Sekunden")), ("60000", _("1 Minute"))])
38 config.plugins.pictureviewer.slideshowmode = ConfigSelection(default="0", choices = [("0", _("normal")), ("1", _("endlos"))])
40 config.plugins.pictureviewer.slideshowext = ConfigText(default=".3ssl")
41 config.plugins.pictureviewer.matchingPattern = ConfigText(default="(?i)^.*\.(jpeg|jpg|jpe|png|bmp|gif)")
42 config.plugins.pictureviewer.slideshowdir = ConfigText(default="/media/hdd/slideshows/")
43 config.plugins.pictureviewer.rootdir = ConfigText(default="/media/")
44 config.plugins.pictureviewer.stopserviceonstart = ConfigYesNo(default = False)
45 SLIDESHOWMODE_NORMAL = 0
46 SLIDESHOWMODE_REPEAT = 1
48 originalservice = None
52 def startPictureviewer(session, **kwargs):
53 global originalservice, mysession
55 originalservice = session.nav.getCurrentlyPlayingServiceReference()
56 if config.plugins.pictureviewer.stopserviceonstart.value:
57 session.nav.stopService()
58 session.openWithCallback(mainCB, PictureViewer)
60 def startWebcamviewer(session, **kwargs):
61 global originalservice, mysession
63 originalservice = session.nav.getCurrentlyPlayingServiceReference()
64 if config.plugins.pictureviewer.stopserviceonstart.value:
65 session.nav.stopService()
66 xmlfile = "/usr/lib/enigma2/python/Plugins/Extensions/WebcamViewer/webcam.xml"
67 if os.path.isfile(xmlfile):
69 xmlnode = xml.dom.minidom.parse(open(xmlfile))
70 session.openWithCallback(mainCB, WebcamViewer, xmlnode.childNodes[1])
74 _("Loading config file failed!\n\n%s") % e,
75 MessageBox.TYPE_WARNING
80 _("Loading config file failed!\n\nconfigfile not found!"),
81 MessageBox.TYPE_WARNING
88 global originalservice, mysession
89 if config.plugins.pictureviewer.stopserviceonstart.value:
90 mysession.nav.playService(originalservice)
92 def Plugins(path, **kwargs):
96 description="browse your local pictures",
97 where = PluginDescriptor.WHERE_PLUGINMENU,
98 fnc = startPictureviewer,
99 icon="pictureviewer.png"
103 description="view webcams around the world",
104 where = PluginDescriptor.WHERE_PLUGINMENU,
105 fnc = startWebcamviewer,
106 icon="webcamviewer.png"
112 class ViewerSelectScreen(Screen):
114 def __init__(self, session, args = 0):
115 skin = """<screen position="93,70" size="550,450">
116 <widget name="list" position="0,0" size="550,450" />
119 Screen.__init__(self, session)
120 self.slideshowfiles = []
121 self.slideshowfiles.append((_("WebcamViewer"),STARTWEBCAMVIEWER))
122 self.slideshowfiles.append((_("online webcam.travel"),STARTWEBCAMTRAVEL))
123 self["list"] = MenuList(self.slideshowfiles)
124 self["actions"] = ActionMap(["WizardActions", "MenuActions", "DirectionActions", "ShortcutActions"],
131 selection = self["list"].getCurrent()
133 self.close(self.session,selection[1])
139 currentslideshowitem = 0
142 def __init__(self, session, callback):
143 self.session = session
144 self.callback = callback
146 def setfiles(self, filelist):
147 self.filelist = filelist
150 if len(self.filelist) > 0:
151 self.currentslideshowitem = -1
152 self.nextSlideshowItem()
154 def nextSlideshowItem(self, prev = False):
155 currentslideshowitem = self.currentslideshowitem
157 currentslideshowitem -= 2
158 if currentslideshowitem < 0:
159 currentslideshowitem = -1
160 if currentslideshowitem is not (len(self.filelist) - 1):
161 currentslideshowitem += 1
162 filetoshow = self.filelist[currentslideshowitem][1]
163 if not self.wbviewer:
164 self.wbviewer = self.session.openWithCallback(
167 filetoshow.split("/")[-1],
169 slideshowcallback = self.nextSlideshowItem
172 self.wbviewer.filename = filetoshow
174 self.currentslideshowitem = currentslideshowitem
175 elif int(config.plugins.pictureviewer.slideshowmode.value) is SLIDESHOWMODE_REPEAT:
176 print "["+myname+"] restarting slideshow"
179 print "["+myname+"] slideshow finished"
186 class PictureViewer(Screen):
189 currList = "slideshowlist"
191 loadedslideshowlistlistname = False
193 def __init__(self, session, args = 0):
194 skin = """<screen position="93,70" size="550,450" title="%s">
195 <widget name="menu" position="1,1" size="275,400" scrollbarMode="showOnDemand" />
196 <widget name="pixmap" position="550,450" size="275,200" backgroundColor="red" />
197 <widget name="slist" position="275,200" size="275,200" scrollbarMode="showOnDemand" />
198 <widget name="buttonred" position="6,405" size="130,40" backgroundColor="red" valign="center" halign="center" zPosition="2" foregroundColor="white" font="Regular;18" />
199 <widget name="buttongreen" position="142,405" size="130,40" backgroundColor="green" valign="center" halign="center" zPosition="2" foregroundColor="white" font="Regular;18" />
200 <widget name="buttonyellow" position="278,405" size="130,40" backgroundColor="yellow" valign="center" halign="center" zPosition="2" foregroundColor="white" font="Regular;18" />
201 <widget name="buttonblue" position="414,405" size="130,40" backgroundColor="blue" valign="center" halign="center" zPosition="2" foregroundColor="white" font="Regular;18" />
202 </screen>""" % config.plugins.pictureviewer.rootdir.value
204 Screen.__init__(self, session)
206 self.filelist = PictureList(config.plugins.pictureviewer.rootdir.value, matchingPattern = config.plugins.pictureviewer.matchingPattern.value)
207 self["menu"] = self.filelist
209 self.picload = ePicLoad()
210 self.picload.PictureData.get().append(self.updateInfoPanelCB)
211 self.picload.setPara((275, 200, 1, 1, False, 1, "#ff000000"))
212 self.preview = Pixmap()
213 self["pixmap"] = self.preview
215 self.slideshowfiles = []
216 self.slideshowlist =MenuList(self.slideshowfiles)
217 self["slist"] = self.slideshowlist
219 self["buttonred"] = Label("")
220 self["buttongreen"] = Label("")
221 self["buttonyellow"] = Label("")
222 self["buttonblue"] = Label("")
224 self["actions"] = ActionMap(["WizardActions", "MenuActions", "DirectionActions", "ShortcutActions"],
228 "menu": self.openMenu,
232 "right": self.rightUp,
234 "green": self.KeyGreen,
235 "yellow": self.KeyYellow,
236 "blue": self.switchList,
239 self.onLayoutFinish.append(self.switchList)
240 self.onLayoutFinish.append(self.updateInfoPanel)
243 if self.currList is "filelist":
244 # adding all files in current dir to slideshowlist
245 dirname = self["menu"].getCurrentDir()
246 if os.path.isdir(dirname):
247 s = os.listdir(dirname)
250 if compile(config.plugins.pictureviewer.matchingPattern.value).search(dirname + file):
251 self.slideshowfiles.append((_(file),dirname + file))
252 self["slist"].l.setList(self.slideshowfiles)
257 for file in os.listdir(config.plugins.pictureviewer.slideshowdir.value):
258 if file.endswith(config.plugins.pictureviewer.slideshowext.value):
259 list.append((_(file.split("/")[-1]),file))
260 self.session.openWithCallback(
261 self.fileToLoadFilelistEntered,
263 _("select List to load"),
267 print "["+myname+"] IOError:",e
269 print "["+myname+"] OSError:",e
272 if self.currList is "filelist" :
275 x = Slideshow(self.session, self.show)
276 x.setfiles(self.slideshowfiles)
280 if not self.loadedslideshowlistlistname:
281 newname = "slideshowlist"
283 newname = self.loadedslideshowlistlistname
284 self.session.openWithCallback(
285 self.fileToSaveFilelistEntered,
287 title = _("Enter filename to save the List:"),
293 def fileToLoadFilelistEntered(self, fileselection):
294 if fileselection is not None:
296 filename = fileselection[1]
297 fp = open(config.plugins.pictureviewer.slideshowdir.value + filename)
299 for x in fp.readlines():
300 file = x.replace("\n","")
301 if x.startswith("#"):
303 elif not os.path.exists(file):
304 print "["+myname+"] loaded file from filelist isnt avaible! ignoreing ->", file
306 list.append((_(file.split("/")[-1]), file))
307 self.slideshowfiles = list
308 self["slist"].l.setList(self.slideshowfiles)
309 self.loadedslideshowlistlistname = filename.replace(config.plugins.pictureviewer.slideshowext.value, "")
311 print "["+myname+"] error:", e
313 def fileToSaveFilelistEntered(self, filename):
314 if filename is not None:
315 print "["+myname+"] saving list to ", config.plugins.pictureviewer.slideshowdir.value+filename + config.plugins.pictureviewer.slideshowext.value
317 if not os.path.exists(config.plugins.pictureviewer.slideshowdir.value):
318 print "+" * 10, os.path.basename(filename)
319 os.mkdir(config.plugins.pictureviewer.slideshowdir.value)
320 fp = open(config.plugins.pictureviewer.slideshowdir.value + filename+config.plugins.pictureviewer.slideshowext.value, "w")
321 fp.write("# this is a slideshow file for "+myname+" made by V"+myversion+"\n")
322 fp.write("# you can make your own... each line with full path of the imagefile\n")
323 fp.write("# by importing this file,we will ignoring a file if is doesnt exist\n")
324 for x in self.slideshowfiles:
325 fp.write(x[1] + "\n")
328 print "["+myname+"] error:", e
331 if self.currList is "filelist":
332 # add picture to list
333 fullfile = self["menu"].getSelection()[0]
334 if os.path.isfile(fullfile):
335 self.slideshowfiles.append((_(fullfile.split("/")[-1]), fullfile))
336 self["slist"].l.setList(self.slideshowfiles)
338 # deleting an Picture
339 if len(self.slideshowfiles) >= 1:
340 indexinlist = self["slist"].l.getCurrentSelectionIndex()
341 self.slideshowfiles.pop(indexinlist)
342 self["slist"].l.setList(self.slideshowfiles)
344 def switchList(self):
345 if self.currList is "filelist" :
346 # Slideshow activieren
347 self.filelist.selectionEnabled(0)
348 self.slideshowlist.selectionEnabled(1)
349 self["buttonred"].setText("speichern")
350 self["buttongreen"].setText("laden")
351 self["buttonyellow"].setText("loeschen")
352 self["buttonblue"].setText("Dateien")
353 self.currList = "slideshowlist"
355 # filelist activieren
356 self.filelist.selectionEnabled(1)
357 self.slideshowlist.selectionEnabled(0)
358 self["buttonred"].setText("starte Slideshow")
359 self["buttongreen"].setText("alle hinzufuegen")
360 self["buttonyellow"].setText("hinzufuegen")
361 self["buttonblue"].setText("Slideshow bearbeiten")
362 self.currList = "filelist"
365 if self.currList is "filelist" :
366 selection = self["menu"].getSelection()
367 if self.filelist.canDescent():
368 self.setTitle(selection[0])
369 self.filelist.descent()
371 if selection[1] == True: # isDir
374 print "["+myname+"] file selected ", selection[0]
375 if os.path.isfile(selection[0]):
376 self.session.open(PictureScreen,selection[0].split("/")[-1], selection[0])
378 print "["+myname+"] file not found ", selection[0]
380 self.updateInfoPanel()
383 if self.currList is "filelist":
385 self.updateInfoPanel()
387 self.slideshowlist.up()
390 if self.currList is "filelist":
391 self.filelist.pageUp()
392 self.updateInfoPanel()
394 self.slideshowlist.pageUp()
397 if self.currList is "filelist":
398 self.filelist.pageDown()
399 self.updateInfoPanel()
401 self.slideshowlist.pageDown()
404 if self.currList is "filelist":
406 self.updateInfoPanel()
408 self.slideshowlist.down()
410 def updateInfoPanel(self):
411 if self.currList is "filelist":
412 selectedfile = self["menu"].getSelection()[0]
414 selectedfile = self["slist"].l.getCurrentSelection()[1]
415 self.picload.startDecode(selectedfile)
417 def updateInfoPanelCB(self, picInfo = None):
418 ptr = self.picload.getData()
420 self["pixmap"].instance.setPixmap(ptr.__deref__())
421 self["pixmap"].move(275,0)
425 def output(self,str):
429 self.session.open(WebcamViewerMenu)
431 class WebcamViewer(Screen):
434 def __init__(self, session,xmlnode, args = 0):
435 self.xmlnode = xmlnode
440 pos_x = (screen_x/2)-(size_x/2)
441 pos_y = (screen_y/2)-(size_y/2)
443 <screen position="%i,%i" size="%i,%i" title="%s">
444 <widget name="menu" position="1,1" size="%i,%i" scrollbarMode="showOnDemand"/>
445 </screen>""" % (pos_x,pos_y,size_x,size_y,myname,size_x,size_y)
447 Screen.__init__(self, session)
449 self.filelist = MenuList(self.getMenuData())
450 self["menu"] = self.filelist
451 self["actions"] = ActionMap(["WizardActions", "DirectionActions"],
456 self.onLayoutFinish.append(self.settingTitle)
458 def settingTitle(self):
459 self.setTitle(myname + ": " + self.menutitle)
462 selected = self["menu"].l.getCurrentSelection()[1]
463 menuitemtitle = self["menu"].l.getCurrentSelection()[0]
466 if menuitemtitle.startswith("webcam.travel"):
467 self.session.openWithCallback(self.cb, TravelWebcamviewer)
468 elif type.startswith("cam"):
469 self.session.open(PictureScreen, menuitemtitle, data)
472 self.session.openWithCallback(self.cb, WebcamViewer, data)
477 def getMenuData(self):
478 xloader = XMLloader()
479 self.menutitle = xloader.getScreenXMLTitle(self.xmlnode)
481 if self.menutitle =="Mainmenu":
482 data.append((_("webcam.travel"), "webcam.travel"))
483 for node in self.xmlnode.childNodes:
484 if node.nodeType != xml.dom.minidom.Element.nodeType or node.tagName != 'menu':
487 nodex['name'] = xloader.get_txt(node, "name", "no name")
488 data.append((_("*" + nodex['name']), ["node", node]))
490 for node in self.xmlnode.childNodes:
491 if node.nodeType != xml.dom.minidom.Element.nodeType or node.tagName != 'cam':
494 nodex['name'] = xloader.get_txt(node, "name", "no name")
495 nodex['url'] =xloader.get_txt(node, "url", "no url")
496 data.append((_(nodex['name']), ["cam", nodex['url']]))
501 class PictureList(MenuList):
502 def __init__(self, directory, matchingPattern = None, enableWrapAround = False):
503 MenuList.__init__(self, None, enableWrapAround, eListboxPythonMultiContent)
504 self.showDirectories = True
505 self.showFiles = True
507 self.matchingPattern = matchingPattern
508 self.changeDir(directory)
509 self.l.setFont(0, gFont("Regular", 18))
510 self.currentDir = directory
512 def getCurrentDir(self):
513 return self.currentDir
515 def getSelection(self):
516 return self.l.getCurrentSelection()[0]
518 def getFileList(self):
521 def changeDir(self, directory):
522 self.currentDir = directory
527 files = os.listdir(directory)
531 if os.path.isdir(directory + "/" + x):
532 directories.append(x)
536 if directory != "/" and self.showDirectories and not self.isTop:
537 self.list.append(self.getPictureEntryComponent("..", '/'.join(directory.split('/')[:-2]) + '/', True))
539 if self.showDirectories:
540 for x in directories:
541 name = (directory+x).split('/')[-1]
542 self.list.append(self.getPictureEntryComponent(name, '/'.join(directory.split('/')[:-1]) + '/' + x + '/', True))
548 if self.matchingPattern is not None:
549 if compile(self.matchingPattern).search(path):
550 self.list.append(self.getPictureEntryComponent(name,path, False))
554 self.l.setList(self.list)
556 def canDescent(self):
557 return self.getSelection()[1]
560 self.changeDir(self.getSelection()[0])
562 def getFilename(self):
563 return self.getSelection()[0].getPath()
565 def getServiceRef(self):
566 return self.getSelection()[0]
568 def postWidgetCreate(self, instance):
569 MenuList.postWidgetCreate(self, instance)
570 instance.setItemHeight(23)
572 def getPictureEntryComponent(self,name, absolute, isDir):
573 """ name={angezeigter Name}, absolute={vollstaendiger Pfad}, isDir={True,False} """
574 res = [ (absolute, isDir) ]
575 res.append((eListboxPythonMultiContent.TYPE_TEXT, 35, 1, 200, 20, 0, 0, name))
577 png = loadPNG("/usr/share/enigma2/extensions/directory.png")
579 extension = name.split('.')
580 extension = extension[-1].lower()
581 if EXTENSIONS.has_key(extension):
582 png = loadPNG("/usr/share/enigma2/extensions/" + EXTENSIONS[extension] + ".png")
586 res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, 10, 2, 20, 20, png))
592 DEFAULT_NAMESPACES = (
593 None, # RSS 0.91, 0.92, 0.93, 0.94, 2.0
594 'http://purl.org/rss/1.0/', # RSS 1.0
595 'http://my.netscape.com/rdf/simple/0.9/' # RSS 0.90
597 DUBLIN_CORE = ('http://purl.org/dc/elements/1.1/',)
598 def getElementsByTagName(self, node, tagName, possibleNamespaces = DEFAULT_NAMESPACES):
599 for namespace in possibleNamespaces:
600 children = node.getElementsByTagNameNS(namespace, tagName)
605 def node_data(self, node, tagName, possibleNamespaces = DEFAULT_NAMESPACES):
606 children = self.getElementsByTagName(node, tagName, possibleNamespaces)
607 node = len(children) and children[0] or None
608 return node and "".join([child.data.encode("utf-8") for child in node.childNodes]) or None
610 def get_txt(self, node, tagName, default_txt = ""):
612 Liefert den Inhalt >tagName< des >node< zurueck, ist dieser nicht
613 vorhanden, wird >default_txt< zurueck gegeben.
615 return self.node_data(node, tagName) or self.node_data(node, tagName, self.DUBLIN_CORE) or default_txt
617 def getScreenXMLTitle(self,node):
618 return self.get_txt(node, "name", "no title")