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
27 from Tools.XMLTools import elementsWithTag
30 from WebcamViewConfig import WebcamViewerMenu
31 from PictureScreen import PictureScreen
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
51 def main1(session, **kwargs):
52 global originalservice, mysession
54 originalservice = session.nav.getCurrentlyPlayingServiceReference()
55 if config.plugins.pictureviewer.stopserviceonstart.value:
56 session.nav.stopService()
57 session.openWithCallback(mainCB, PictureViewer)
59 def main2(session, **kwargs):
60 global originalservice, mysession
62 originalservice = session.nav.getCurrentlyPlayingServiceReference()
63 if config.plugins.pictureviewer.stopserviceonstart.value:
64 session.nav.stopService()
65 xmlfile = "/usr/lib/enigma2/python/Plugins/Extensions/WebcamViewer/webcam.xml"
66 if os.path.isfile(xmlfile):
68 xmlnode = xml.dom.minidom.parse(open(xmlfile))
69 session.openWithCallback(mainCB, WebcamViewer, xmlnode.childNodes[1])
73 _("Loading config file failed!\n\n%s") % e,
74 MessageBox.TYPE_WARNING
79 _("Loading config file failed!\n\nconfigfile not found!"),
80 MessageBox.TYPE_WARNING
84 global originalservice, mysession
85 if config.plugins.pictureviewer.stopserviceonstart.value:
86 mysession.nav.playService(originalservice)
88 def Plugins(path, **kwargs):
92 description="browse your local pictures",
93 where = PluginDescriptor.WHERE_PLUGINMENU,
95 icon="pictureviewer.png"
99 description="view webcams around the world",
100 where = PluginDescriptor.WHERE_PLUGINMENU,
102 icon="webcamviewer.png"
110 currentslideshowitem = 0
113 def __init__(self, session, callback):
114 self.session = session
115 self.callback = callback
117 def setfiles(self, filelist):
118 self.filelist = filelist
121 if len(self.filelist) > 0:
122 self.currentslideshowitem = -1
123 self.nextSlideshowItem()
125 def nextSlideshowItem(self):
126 if self.currentslideshowitem is not (len(self.filelist) - 1):
127 self.currentslideshowitem = self.currentslideshowitem + 1
128 filetoshow = self.filelist[self.currentslideshowitem][1]
129 if not self.wbviewer:
130 self.wbviewer = self.session.openWithCallback(
133 filetoshow.split("/")[-1],
135 slideshowcallback = self.nextSlideshowItem
138 self.wbviewer.filename = filetoshow
140 elif self.currentslideshowitem is (len(self.filelist) - 1) and int(config.plugins.pictureviewer.slideshowmode.value) is SLIDESHOWMODE_REPEAT:
141 print "["+myname+"] restarting slideshow"
144 print "["+myname+"] slideshow finished"
151 class PictureViewer(Screen):
154 currList = "slideshowlist"
156 loadedslideshowlistlistname = False
158 def __init__(self, session, args = 0):
159 skin = """<screen position="93,70" size="550,450" title="%s">
160 <widget name="menu" position="1,1" size="275,400" scrollbarMode="showOnDemand" />
161 <widget name="pixmap" position="550,450" size="275,200" backgroundColor="red" />
162 <widget name="slist" position="275,200" size="275,200" scrollbarMode="showOnDemand" />
163 <widget name="buttonred" position="6,405" size="130,40" backgroundColor="red" valign="center" halign="center" zPosition="2" foregroundColor="white" font="Regular;18" />
164 <widget name="buttongreen" position="142,405" size="130,40" backgroundColor="green" valign="center" halign="center" zPosition="2" foregroundColor="white" font="Regular;18" />
165 <widget name="buttonyellow" position="278,405" size="130,40" backgroundColor="yellow" valign="center" halign="center" zPosition="2" foregroundColor="white" font="Regular;18" />
166 <widget name="buttonblue" position="414,405" size="130,40" backgroundColor="blue" valign="center" halign="center" zPosition="2" foregroundColor="white" font="Regular;18" />
167 </screen>""" % config.plugins.pictureviewer.rootdir.value
169 Screen.__init__(self, session)
171 self.filelist = PictureList(config.plugins.pictureviewer.rootdir.value, matchingPattern = config.plugins.pictureviewer.matchingPattern.value)
172 self["menu"] = self.filelist
174 self.picload = ePicLoad()
175 self.picload.PictureData.get().append(self.updateInfoPanelCB)
176 self.picload.setPara((275, 200, 1, 1, False, 1, "#ff000000"))
177 self.preview = Pixmap()
178 self["pixmap"] = self.preview
180 self.slideshowfiles = []
181 self.slideshowlist =MenuList(self.slideshowfiles)
182 self["slist"] = self.slideshowlist
184 self["buttonred"] = Label("")
185 self["buttongreen"] = Label("")
186 self["buttonyellow"] = Label("")
187 self["buttonblue"] = Label("")
189 self["actions"] = ActionMap(["WizardActions", "MenuActions", "DirectionActions", "ShortcutActions"],
193 "menu": self.openMenu,
197 "right": self.rightUp,
199 "green": self.KeyGreen,
200 "yellow": self.KeyYellow,
201 "blue": self.switchList,
204 self.onLayoutFinish.append(self.switchList)
205 self.onLayoutFinish.append(self.updateInfoPanel)
208 if self.currList is "filelist":
209 # adding all files in current dir to slideshowlist
210 dirname = self["menu"].getCurrentDir()
211 if os.path.isdir(dirname):
212 s = os.listdir(dirname)
215 if compile(config.plugins.pictureviewer.matchingPattern.value).search(dirname + file):
216 self.slideshowfiles.append((_(file),dirname + file))
217 self["slist"].l.setList(self.slideshowfiles)
222 for file in os.listdir(config.plugins.pictureviewer.slideshowdir.value):
223 if file.endswith(config.plugins.pictureviewer.slideshowext.value):
224 list.append((_(file.split("/")[-1]),file))
225 self.session.openWithCallback(
226 self.fileToLoadFilelistEntered,
228 _("select List to load"),
232 print "["+myname+"] IOError:",e
234 print "["+myname+"] OSError:",e
237 if self.currList is "filelist" :
240 x = Slideshow(self.session, self.show)
241 x.setfiles(self.slideshowfiles)
245 if not self.loadedslideshowlistlistname:
246 newname = "slideshowlist"
248 newname = self.loadedslideshowlistlistname
249 self.session.openWithCallback(
250 self.fileToSaveFilelistEntered,
252 title = _("Enter filename to save the List:"),
258 def fileToLoadFilelistEntered(self, fileselection):
259 if fileselection is not None:
261 filename = fileselection[1]
262 fp = open(config.plugins.pictureviewer.slideshowdir.value + filename)
264 for x in fp.readlines():
265 file = x.replace("\n","")
266 if x.startswith("#"):
268 elif not os.path.exists(file):
269 print "["+myname+"] loaded file from filelist isnt avaible! ignoreing ->", file
271 list.append((_(file.split("/")[-1]), file))
272 self.slideshowfiles = list
273 self["slist"].l.setList(self.slideshowfiles)
274 self.loadedslideshowlistlistname = filename.replace(config.plugins.pictureviewer.slideshowext.value, "")
276 print "["+myname+"] error:", e
278 def fileToSaveFilelistEntered(self, filename):
279 if filename is not None:
280 print "["+myname+"] saving list to ", config.plugins.pictureviewer.slideshowdir.value+filename + config.plugins.pictureviewer.slideshowext.value
282 if not os.path.exists(config.plugins.pictureviewer.slideshowdir.value):
283 print "+" * 10, os.path.basename(filename)
284 os.mkdir(config.plugins.pictureviewer.slideshowdir.value)
285 fp = open(config.plugins.pictureviewer.slideshowdir.value + filename+config.plugins.pictureviewer.slideshowext.value, "w")
286 fp.write("# this is a slideshow file for "+myname+" made by V"+myversion+"\n")
287 fp.write("# you can make your own... each line with full path of the imagefile\n")
288 fp.write("# by importing this file,we will ignoring a file if is doesnt exist\n")
289 for x in self.slideshowfiles:
290 fp.write(x[1] + "\n")
293 print "["+myname+"] error:", e
296 if self.currList is "filelist":
297 # add picture to list
298 fullfile = self["menu"].getSelection()[0]
299 if os.path.isfile(fullfile):
300 self.slideshowfiles.append((_(fullfile.split("/")[-1]), fullfile))
301 self["slist"].l.setList(self.slideshowfiles)
303 # deleting an Picture
304 if len(self.slideshowfiles) >= 1:
305 indexinlist = self["slist"].l.getCurrentSelectionIndex()
306 self.slideshowfiles.pop(indexinlist)
307 self["slist"].l.setList(self.slideshowfiles)
309 def switchList(self):
310 if self.currList is "filelist" :
311 # Slideshow activieren
312 self.filelist.selectionEnabled(0)
313 self.slideshowlist.selectionEnabled(1)
314 self["buttonred"].setText("speichern")
315 self["buttongreen"].setText("laden")
316 self["buttonyellow"].setText("loeschen")
317 self["buttonblue"].setText("Dateien")
318 self.currList = "slideshowlist"
320 # filelist activieren
321 self.filelist.selectionEnabled(1)
322 self.slideshowlist.selectionEnabled(0)
323 self["buttonred"].setText("starte Slideshow")
324 self["buttongreen"].setText("alle hinzufuegen")
325 self["buttonyellow"].setText("hinzufuegen")
326 self["buttonblue"].setText("Slideshow bearbeiten")
327 self.currList = "filelist"
330 if self.currList is "filelist" :
331 selection = self["menu"].getSelection()
332 if self.filelist.canDescent():
333 self.setTitle(selection[0])
334 self.filelist.descent()
336 if selection[1] == True: # isDir
339 print "["+myname+"] file selected ", selection[0]
340 if os.path.isfile(selection[0]):
341 self.session.open(PictureScreen,selection[0].split("/")[-1], selection[0])
343 print "["+myname+"] file not found ", selection[0]
345 self.updateInfoPanel()
348 if self.currList is "filelist":
350 self.updateInfoPanel()
352 self.slideshowlist.up()
355 if self.currList is "filelist":
356 self.filelist.pageUp()
357 self.updateInfoPanel()
359 self.slideshowlist.pageUp()
362 if self.currList is "filelist":
363 self.filelist.pageDown()
364 self.updateInfoPanel()
366 self.slideshowlist.pageDown()
369 if self.currList is "filelist":
371 self.updateInfoPanel()
373 self.slideshowlist.down()
375 def updateInfoPanel(self):
376 if self.currList is "filelist":
377 selectedfile = self["menu"].getSelection()[0]
379 selectedfile = self["slist"].l.getCurrentSelection()[1]
380 self.picload.startDecode(selectedfile)
382 def updateInfoPanelCB(self, picInfo = None):
383 ptr = self.picload.getData()
385 self["pixmap"].instance.setPixmap(ptr.__deref__())
386 self["pixmap"].move(275,0)
390 def output(self,str):
394 self.session.open(WebcamViewerMenu)
396 class WebcamViewer(Screen):
399 def __init__(self, session,xmlnode, args = 0):
400 self.xmlnode = xmlnode
405 pos_x = (screen_x/2)-(size_x/2)
406 pos_y = (screen_y/2)-(size_y/2)
408 <screen position="%i,%i" size="%i,%i" title="%s">
409 <widget name="menu" position="1,1" size="%i,%i" scrollbarMode="showOnDemand"/>
410 </screen>""" % (pos_x,pos_y,size_x,size_y,myname,size_x,size_y)
412 Screen.__init__(self, session)
414 self.filelist = MenuList(self.getMenuData())
415 self["menu"] = self.filelist
416 self["actions"] = ActionMap(["WizardActions", "DirectionActions"],
421 self.onLayoutFinish.append(self.settingTitle)
423 def settingTitle(self):
424 self.setTitle(myname + ": " + self.menutitle)
427 selected = self["menu"].l.getCurrentSelection()[1]
428 menuitemtitle = self["menu"].l.getCurrentSelection()[0]
431 if type.startswith("cam"):
432 self.session.open(PictureScreen, menuitemtitle, data)
435 self.session.openWithCallback(self.cb, WebcamViewer, data)
440 def getMenuData(self):
441 xloader = XMLloader()
442 self.menutitle = xloader.getScreenXMLTitle(self.xmlnode)
444 for node in elementsWithTag(self.xmlnode._get_childNodes(), 'menu'):
446 nodex['name'] = xloader.get_txt(node, "name", "no name")
447 data.append((_("*" + nodex['name']), ["node", node]))
449 for node in elementsWithTag(self.xmlnode._get_childNodes(), 'cam'):
451 nodex['name'] = xloader.get_txt(node, "name", "no name")
452 nodex['url'] =xloader.get_txt(node, "url", "no url")
453 data.append((_(nodex['name']), ["cam", nodex['url']]))
458 class PictureList(MenuList):
459 def __init__(self, directory, matchingPattern = None, enableWrapAround = False):
460 MenuList.__init__(self, None, enableWrapAround, eListboxPythonMultiContent)
461 self.showDirectories = True
462 self.showFiles = True
464 self.matchingPattern = matchingPattern
465 self.changeDir(directory)
466 self.l.setFont(0, gFont("Regular", 18))
467 self.currentDir = directory
469 def getCurrentDir(self):
470 return self.currentDir
472 def getSelection(self):
473 return self.l.getCurrentSelection()[0]
475 def getFileList(self):
478 def changeDir(self, directory):
479 self.currentDir = directory
484 files = os.listdir(directory)
488 if os.path.isdir(directory + "/" + x):
489 directories.append(x)
493 if directory != "/" and self.showDirectories and not self.isTop:
494 self.list.append(self.getPictureEntryComponent("..", '/'.join(directory.split('/')[:-2]) + '/', True))
496 if self.showDirectories:
497 for x in directories:
498 name = (directory+x).split('/')[-1]
499 self.list.append(self.getPictureEntryComponent(name, '/'.join(directory.split('/')[:-1]) + '/' + x + '/', True))
505 if self.matchingPattern is not None:
506 if compile(self.matchingPattern).search(path):
507 self.list.append(self.getPictureEntryComponent(name,path, False))
511 self.l.setList(self.list)
513 def canDescent(self):
514 return self.getSelection()[1]
517 self.changeDir(self.getSelection()[0])
519 def getFilename(self):
520 return self.getSelection()[0].getPath()
522 def getServiceRef(self):
523 return self.getSelection()[0]
525 def postWidgetCreate(self, instance):
526 MenuList.postWidgetCreate(self, instance)
527 instance.setItemHeight(23)
529 def getPictureEntryComponent(self,name, absolute, isDir):
530 """ name={angezeigter Name}, absolute={vollstaendiger Pfad}, isDir={True,False} """
531 res = [ (absolute, isDir) ]
532 res.append((eListboxPythonMultiContent.TYPE_TEXT, 35, 1, 200, 20, 0, 0, name))
534 png = loadPNG("/usr/share/enigma2/extensions/directory.png")
536 extension = name.split('.')
537 extension = extension[-1].lower()
538 if EXTENSIONS.has_key(extension):
539 png = loadPNG("/usr/share/enigma2/extensions/" + EXTENSIONS[extension] + ".png")
543 res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, 10, 2, 20, 20, png))
549 DEFAULT_NAMESPACES = (
550 None, # RSS 0.91, 0.92, 0.93, 0.94, 2.0
551 'http://purl.org/rss/1.0/', # RSS 1.0
552 'http://my.netscape.com/rdf/simple/0.9/' # RSS 0.90
554 DUBLIN_CORE = ('http://purl.org/dc/elements/1.1/',)
555 def getElementsByTagName(self, node, tagName, possibleNamespaces = DEFAULT_NAMESPACES):
556 for namespace in possibleNamespaces:
557 children = node.getElementsByTagNameNS(namespace, tagName)
562 def node_data(self, node, tagName, possibleNamespaces = DEFAULT_NAMESPACES):
563 children = self.getElementsByTagName(node, tagName, possibleNamespaces)
564 node = len(children) and children[0] or None
565 return node and "".join([child.data.encode("utf-8") for child in node.childNodes]) or None
567 def get_txt(self, node, tagName, default_txt = ""):
569 Liefert den Inhalt >tagName< des >node< zurueck, ist dieser nicht
570 vorhanden, wird >default_txt< zurueck gegeben.
572 return self.node_data(node, tagName) or self.node_data(node, tagName, self.DUBLIN_CORE) or default_txt
574 def getScreenXMLTitle(self,node):
575 return self.get_txt(node, "name", "no title")