--- /dev/null
+from enigma import eListbox\r
+from enigma import eListboxPythonMultiContent\r
+from enigma import loadPic\r
+from enigma import loadPNG\r
+from enigma import gFont\r
+### Picturelist\r
+from Components.HTMLComponent import HTMLComponent\r
+from Components.GUIComponent import GUIComponent\r
+from Screens.Screen import Screen\r
+from Screens.MessageBox import MessageBox\r
+from Screens.InputBox import InputBox\r
+from Screens.ChoiceBox import ChoiceBox\r
+from Components.ActionMap import ActionMap, NumberActionMap\r
+from Components.ScrollLabel import ScrollLabel\r
+from Components.Label import Label\r
+from Components.MenuList import MenuList\r
+from Components.FileList import EXTENSIONS\r
+## configmenu\r
+from Components.config import config, ConfigSubsection,ConfigSelection,ConfigText,getConfigListEntry\r
+from Components.ConfigList import ConfigListScreen\r
+####\r
+from Components.Input import Input\r
+from Components.Pixmap import Pixmap\r
+from Plugins.Plugin import PluginDescriptor\r
+### System\r
+import os\r
+import re\r
+## XML\r
+from pyexpat import ExpatError\r
+import xml.dom.minidom\r
+from Tools.XMLTools import mergeText, elementsWithTag\r
+\r
+### my\r
+from WebcamViewConfig import WebcamViewerMenu\r
+from PictureScreen import PictureScreen\r
+###\r
+myname = "Webcam/Picture Viewer" \r
+myversion = "1.1"\r
+\r
+\r
+\r
+config.plugins.pictureviewer = ConfigSubsection()\r
+config.plugins.pictureviewer.slideshowtime = ConfigSelection(default="5000", choices = [("5000", _("5 Sekunden")), ("10000", _("10 Sekunden")), ("20000", _("20 Sekunden")), ("60000", _("1 Minute"))])\r
+config.plugins.pictureviewer.slideshowmode = ConfigSelection(default="0", choices = [("0", _("normal")), ("1", _("endlos"))])\r
+#not editable configs\r
+config.plugins.pictureviewer.slideshowext = ConfigText(default=".3ssl")\r
+config.plugins.pictureviewer.matchingPattern = ConfigText(default="(?i)^.*\.(jpeg|jpg|jpe|png|bmp|gif)")\r
+config.plugins.pictureviewer.slideshowdir = ConfigText(default="/media/hdd/slideshows/")\r
+config.plugins.pictureviewer.rootdir = ConfigText(default="/media/")\r
+SLIDESHOWMODE_NORMAL = 0\r
+SLIDESHOWMODE_REPEAT = 1\r
+\r
+ \r
+def main1(session,**kwargs):\r
+ session.open(PictureViewer)\r
+\r
+def main2(session,**kwargs):\r
+ xmlfile = "/usr/lib/enigma2/python/Plugins/Extensions/WebcamViewer/webcam.xml"\r
+ if os.path.isfile(xmlfile):\r
+ try:\r
+ xmlnode = xml.dom.minidom.parse( open(xmlfile) )\r
+ session.open(WebcamViewer,xmlnode.childNodes[1])\r
+ except ExpatError,e:\r
+ session.open(MessageBox,_("Loading config file failed!\n\n%s"%e), MessageBox.TYPE_WARNING)\r
+ else:\r
+ session.open(MessageBox,_("Loading config file failed!\n\nconfigfile not found!"), MessageBox.TYPE_WARNING)\r
+ \r
+ \r
+def Plugins(path,**kwargs):\r
+ p = [\r
+ PluginDescriptor(\r
+ name="PictureViewer", \r
+ description="browse your local pictures", \r
+ where = PluginDescriptor.WHERE_PLUGINMENU,\r
+ fnc = main1\r
+ )\r
+ ,\r
+ PluginDescriptor(\r
+ name="WebcamViewer", \r
+ description="view webcams around the world", \r
+ where = PluginDescriptor.WHERE_PLUGINMENU,\r
+ fnc = main2\r
+ )\r
+ ]\r
+ return p \r
+\r
+\r
+ \r
+\r
+###################\r
+class Slideshow:\r
+ filelist=[]\r
+ currentslideshowitem =0\r
+ wbviewer = False\r
+ def __init__(self,session,callback):\r
+ self.session = session\r
+ self.callback = callback\r
+ def setfiles(self,filelist):\r
+ self.filelist = filelist \r
+\r
+ def start(self):\r
+ if len(self.filelist)>0: \r
+ self.currentslideshowitem = -1\r
+ self.nextSlideshowItem()\r
+ \r
+ def nextSlideshowItem(self):\r
+ if self.currentslideshowitem is not (len(self.filelist)-1):\r
+ self.currentslideshowitem = self.currentslideshowitem+1\r
+ filetoshow = self.filelist[self.currentslideshowitem][1]\r
+ if self.wbviewer is False:\r
+ self.wbviewer = self.session.openWithCallback(self.cb,PictureScreen,filetoshow.split("/")[-1],filetoshow,slideshowcallback=self.nextSlideshowItem) \r
+ else:\r
+ self.wbviewer.filename = filetoshow\r
+ self.wbviewer.do() \r
+ elif self.currentslideshowitem is (len(self.filelist)-1) and int(config.plugins.pictureviewer.slideshowmode.value) is SLIDESHOWMODE_REPEAT:\r
+ print "["+myname+"] restarting slideshow"\r
+ self.start()\r
+ else:\r
+ print "["+myname+"] slideshow finished"\r
+ self.wbviewer.exit()\r
+ self.cb()\r
+ def cb(self):\r
+ self.callback()\r
+###################\r
+class PictureViewer(Screen):\r
+ skin = ""\r
+ filelist = []\r
+ currList = "slideshowlist"\r
+ wbviewer = False\r
+ loadedslideshowlistlistname = False\r
+ def __init__(self, session, args = 0):\r
+ self.session = session\r
+ s = "<screen position=\"93,70\" size=\"550,450\" title=\"%s\">\n" %config.plugins.pictureviewer.rootdir.value\r
+ s = s+"<widget name=\"menu\" position=\"1,1\" size=\"275,400\" scrollbarMode=\"showOnDemand\" />\n"\r
+ s = s+"<widget name=\"pixmap\" position=\"550,450\" size=\"275,200\" backgroundColor=\"red\"/>\n" \r
+ s = s+"<widget name=\"slist\" position=\"275,200\" size=\"275,200\" scrollbarMode=\"showOnDemand\"/>\n" \r
+ s = s+"<widget name=\"buttonred\" position=\"6,405\" size=\"130,40\" backgroundColor=\"red\" valign=\"center\" halign=\"center\" zPosition=\"2\" foregroundColor=\"white\" font=\"Regular;18\"/>\n" \r
+ s = s+"<widget name=\"buttongreen\" position=\"142,405\" size=\"130,40\" backgroundColor=\"green\" valign=\"center\" halign=\"center\" zPosition=\"2\" foregroundColor=\"white\" font=\"Regular;18\"/>\n" \r
+ s = s+"<widget name=\"buttonyellow\" position=\"278,405\" size=\"130,40\" backgroundColor=\"yellow\" valign=\"center\" halign=\"center\" zPosition=\"2\" foregroundColor=\"white\" font=\"Regular;18\"/>\n" \r
+ s = s+"<widget name=\"buttonblue\" position=\"414,405\" size=\"130,40\" backgroundColor=\"blue\" valign=\"center\" halign=\"center\" zPosition=\"2\" foregroundColor=\"white\" font=\"Regular;18\"/>\n" \r
+ self.skin = s+"</screen>"\r
+ Screen.__init__(self, session)\r
+ self.filelist = PictureList(config.plugins.pictureviewer.rootdir.value, matchingPattern = config.plugins.pictureviewer.matchingPattern.value)\r
+ self["menu"] = self.filelist\r
+ self.preview = Pixmap()\r
+ self["pixmap"] = self.preview\r
+ self.slideshowfiles = []\r
+ self.slideshowlist =MenuList(self.slideshowfiles)\r
+ self["slist"] = self.slideshowlist\r
+ self["buttonred"] = Label("")\r
+ self["buttongreen"] = Label("")\r
+ self["buttonyellow"] = Label("")\r
+ self["buttonblue"] = Label("")\r
+ self["actions"] = ActionMap(["WizardActions","MenuActions", "DirectionActions","ShortcutActions"], \r
+ {\r
+ "ok": self.go,\r
+ "back": self.close,\r
+ "menu": self.openMenu,\r
+ "up": self.up,\r
+ "down": self.down,\r
+ "left": self.leftUp,\r
+ "right": self.rightUp,\r
+ "red": self.KeyRed,\r
+ "green": self.KeyGreen,\r
+ "yellow": self.KeyYellow,\r
+ "blue": self.switchList,\r
+ }, -1)\r
+ self.onLayoutFinish.append(self.switchList)\r
+ self.onLayoutFinish.append(self.updateInfoPanel)\r
+ def KeyGreen(self):\r
+ if self.currList is "filelist" :\r
+ ## adding all files in current dir to slideshowlist\r
+ dirname = self["menu"].getCurrentDir()\r
+ if os.path.isdir(dirname):\r
+ s = os.listdir(dirname)\r
+ s.sort()\r
+ for file in s:\r
+ if re.compile(config.plugins.pictureviewer.matchingPattern.value).search(dirname+file):\r
+ self.slideshowfiles.append((_(file),dirname+file))\r
+ self["slist"].l.setList(self.slideshowfiles)\r
+ \r
+ else:\r
+ #loading list\r
+ list = []\r
+ try:\r
+ for file in os.listdir(config.plugins.pictureviewer.slideshowdir.value):\r
+ if file.endswith(config.plugins.pictureviewer.slideshowext.value):\r
+ list.append((_(file.split("/")[-1]),file))\r
+ self.session.openWithCallback(self.fileToLoadFilelistEntered,ChoiceBox,_("select List to load"),list)\r
+ except IOError,e:\r
+ print "["+myname+"] IOError:",e\r
+ except OSError,e:\r
+ print "["+myname+"] OSError:",e\r
+ \r
+ def KeyRed(self):\r
+ if self.currList is "filelist" :\r
+ #do slideshow\r
+ self.hide()\r
+ x = Slideshow(self.session,self.show)\r
+ x.setfiles(self.slideshowfiles)\r
+ x.start()\r
+ else:\r
+ # save filelist\r
+ if self.loadedslideshowlistlistname is False:\r
+ newname = "slideshowlist"\r
+ else:\r
+ newname = self.loadedslideshowlistlistname\r
+ self.session.openWithCallback(self.fileToSaveFilelistEntered,InputBox, title=_("Enter filename to save the List:"), text=newname, maxSize=False, type=Input.TEXT)\r
+\r
+ def fileToLoadFilelistEntered(self,fileselection):\r
+ if fileselection is not None: \r
+ try:\r
+ filename = fileselection[1]\r
+ fp = open(config.plugins.pictureviewer.slideshowdir.value+filename)\r
+ list = []\r
+ for x in fp.readlines():\r
+ file = x.replace("\n","")\r
+ if x.startswith("#"):\r
+ pass\r
+ elif os.path.exists(file) is not True:\r
+ print "["+myname+"] loaded file from filelist isnt avaible! ignoreing ->",file\r
+ else:\r
+ list.append((_(file.split("/")[-1]),file))\r
+ self.slideshowfiles =list\r
+ self["slist"].l.setList(self.slideshowfiles)\r
+ self.loadedslideshowlistlistname = filename.replace(config.plugins.pictureviewer.slideshowext.value,"")\r
+ except IOError,e:\r
+ print "["+myname+"] error:",e\r
+ \r
+ def fileToSaveFilelistEntered(self,filename):\r
+ if filename is not None: \r
+ print "["+myname+"] saving list to ",config.plugins.pictureviewer.slideshowdir.value+filename+config.plugins.pictureviewer.slideshowext.value\r
+ try:\r
+ if os.path.exists(config.plugins.pictureviewer.slideshowdir.value) is not True:\r
+ print "+"*10,os.path.basename(filename)\r
+ os.mkdir(config.plugins.pictureviewer.slideshowdir.value)\r
+ fp = open(config.plugins.pictureviewer.slideshowdir.value+filename+config.plugins.pictureviewer.slideshowext.value,"w")\r
+ fp.write("# this is a slideshow file for "+myname+" made by V"+myversion+"\n")\r
+ fp.write("# you can make your own... each line with full path of the imagefile\n")\r
+ fp.write("# by importing this file,we will ignoring a file if is doesnt exist\n")\r
+ for x in self.slideshowfiles:\r
+ fp.write(x[1]+"\n")\r
+ fp.close()\r
+ except IOError,e:\r
+ print "["+myname+"] error:",e\r
+ def KeyYellow(self):\r
+ if self.currList is "filelist" :\r
+ # add picture to list\r
+ fullfile = self["menu"].getSelection()[0]\r
+ if os.path.isfile(fullfile):\r
+ self.slideshowfiles.append((_(fullfile.split("/")[-1]),fullfile))\r
+ self["slist"].l.setList(self.slideshowfiles)\r
+ else:\r
+ # deleting an Picture\r
+ if len(self.slideshowfiles) >=1:\r
+ indexinlist = self["slist"].l.getCurrentSelectionIndex()\r
+ self.slideshowfiles.pop(indexinlist)\r
+ self["slist"].l.setList(self.slideshowfiles)\r
+\r
+ def switchList(self):\r
+ if self.currList is "filelist" :\r
+ # Slideshow activieren\r
+ self.filelist.selectionEnabled(0)\r
+ self.slideshowlist.selectionEnabled(1)\r
+ self["buttonred"].setText("speichern")\r
+ self["buttongreen"].setText("laden")\r
+ self["buttonyellow"].setText("loeschen") \r
+ self["buttonblue"].setText("Dateien")\r
+ self.currList = "slideshowlist"\r
+ else:\r
+ # filelist activieren\r
+ self.filelist.selectionEnabled(1)\r
+ self.slideshowlist.selectionEnabled(0)\r
+ self["buttonred"].setText("starte Slideshow")\r
+ self["buttongreen"].setText("alle hinzufuegen")\r
+ self["buttonyellow"].setText("hinzufuegen") \r
+ self["buttonblue"].setText("Slideshow bearbeiten")\r
+ self.currList = "filelist"\r
+ \r
+ def go(self):\r
+ if self.currList is "filelist" :\r
+ selection = self["menu"].getSelection()\r
+ if self.filelist.canDescent():\r
+ self.setTitle(selection[0])\r
+ self.filelist.descent()\r
+ else:\r
+ if selection[1] == True: # isDir\r
+ pass\r
+ else:\r
+ print "["+myname+"] file selected ",selection[0]\r
+ if os.path.isfile(selection[0]):\r
+ self.session.open(PictureScreen,selection[0].split("/")[-1],selection[0])\r
+ else:\r
+ print "["+myname+"] file not found " + selection[0]+""\r
+ else:\r
+ self.updateInfoPanel()\r
+ def up(self):\r
+ if self.currList is "filelist" :\r
+ self.filelist.up()\r
+ self.updateInfoPanel()\r
+ else:\r
+ self.slideshowlist.up()\r
+ def leftUp(self):\r
+ if self.currList is "filelist" :\r
+ self.filelist.pageUp() \r
+ self.updateInfoPanel()\r
+ else:\r
+ self.slideshowlist.pageUp()\r
+ def rightUp(self):\r
+ if self.currList is "filelist" :\r
+ self.filelist.pageDown()\r
+ self.updateInfoPanel()\r
+ else:\r
+ self.slideshowlist.pageDown()\r
+ def down(self):\r
+ if self.currList is "filelist" :\r
+ self.filelist.down()\r
+ self.updateInfoPanel()\r
+ else:\r
+ self.slideshowlist.down()\r
+ \r
+ def updateInfoPanel(self):\r
+ if self.currList is "filelist" :\r
+ selectedfile = self["menu"].getSelection()[0]\r
+ else:\r
+ selectedfile = self["slist"].l.getCurrentSelection()[1]\r
+ pixmap = loadPic(selectedfile, 275,200, 1,1, 0,1)\r
+ if pixmap is not None:\r
+ self["pixmap"].instance.setPixmap(pixmap.__deref__())\r
+ self["pixmap"].move(275,0)\r
+ else:\r
+ pass\r
+ \r
+ def output(self,str):\r
+ print "+"*10,str \r
+ def openMenu(self):\r
+ self.session.open(WebcamViewerMenu)\r
+###################\r
+class WebcamViewer(Screen):\r
+ skin = ""\r
+ filelist = []\r
+ def __init__(self, session,xmlnode, args = 0):\r
+ self.xmlnode = xmlnode\r
+ screen_x = 736\r
+ screen_y = 576\r
+ size_x = 350\r
+ size_y = 250\r
+ pos_x = (screen_x/2)-(size_x/2)\r
+ pos_y = (screen_y/2)-(size_y/2)\r
+ self.session = session\r
+ self.skin = """\r
+ <screen position="%i,%i" size="%i,%i" title="%s">\r
+ <widget name="menu" position="1,1" size="%i,%i" scrollbarMode="showOnDemand"/>\r
+ </screen>""" % (pos_x,pos_y,size_x,size_y,myname,size_x,size_y) \r
+ Screen.__init__(self, session)\r
+ self.filelist = MenuList(self.getMenuData())\r
+ self["menu"] = self.filelist\r
+ self["actions"] = ActionMap(["WizardActions", "DirectionActions"], \r
+ {\r
+ "ok": self.go,\r
+ "back": self.close,\r
+ }, -1)\r
+ self.onLayoutFinish.append(self.settingTitle)\r
+ \r
+ def settingTitle(self):\r
+ self.setTitle(myname+": "+self.menutitle)\r
+ \r
+ def go(self):\r
+ selected = self["menu"].l.getCurrentSelection()[1]\r
+ menuitemtitle = self["menu"].l.getCurrentSelection()[0]\r
+ type = selected[0]\r
+ data = selected[1]\r
+ if type.startswith("cam"):\r
+ self.session.open(PictureScreen,menuitemtitle,data)\r
+ else:\r
+ self.hide()\r
+ self.session.openWithCallback(self.cb,WebcamViewer,data)\r
+\r
+ def cb(self):\r
+ self.show() \r
+ \r
+ def getMenuData(self):\r
+ xloader = XMLloader()\r
+ self.menutitle = xloader.getScreenXMLTitle(self.xmlnode)\r
+ data =[] \r
+ for node in elementsWithTag(self.xmlnode._get_childNodes(), 'menu'):\r
+ nodex={}\r
+ nodex['name'] = xloader.get_txt( node, "name", "no name" )\r
+ data.append((_("*"+nodex['name']),["node",node]))\r
+ \r
+ for node2 in elementsWithTag(self.xmlnode._get_childNodes(), 'cam'):\r
+ nodex={}\r
+ nodex['name'] = xloader.get_txt( node2, "name", "no name" )\r
+ nodex['url'] = xloader.get_txt( node2, "url", "no url" )\r
+ data.append((_(nodex['name']),["cam",nodex['url']]))\r
+ return data\r
+###################\r
+\r
+##################\r
+class PictureList(MenuList, HTMLComponent, GUIComponent):\r
+ def __init__(self, directory, matchingPattern = None):\r
+ GUIComponent.__init__(self)\r
+ self.l = eListboxPythonMultiContent()\r
+ self.showDirectories = True\r
+ self.showFiles = True\r
+ self.isTop = False\r
+ self.matchingPattern = matchingPattern\r
+ self.changeDir(directory)\r
+ self.l.setFont(0, gFont("Regular", 18))\r
+ self.currentDir = directory\r
+ \r
+ def getCurrentDir(self):\r
+ return self.currentDir\r
+ \r
+ def getSelection(self):\r
+ return self.l.getCurrentSelection()[0]\r
+ \r
+ def getFileList(self):\r
+ return self.list\r
+ \r
+ def changeDir(self, directory):\r
+ self.currentDir = directory\r
+ self.list = []\r
+ \r
+ directories = []\r
+ files = []\r
+ files = os.listdir(directory)\r
+ files.sort()\r
+ tmpfiles = files[:]\r
+ for x in tmpfiles:\r
+ if os.path.isdir(directory +"/"+ x):\r
+ directories.append(x)\r
+ files.remove(x)\r
+ directories.sort()\r
+ files.sort()\r
+ if directory != "/" and self.showDirectories and not self.isTop:\r
+ self.list.append(self.getPictureEntryComponent("..",'/'.join(directory.split('/')[:-2]) + '/',True))\r
+\r
+ if self.showDirectories:\r
+ for x in directories:\r
+ name = (directory+x).split('/')[-1]\r
+ self.list.append(self.getPictureEntryComponent(name,'/'.join(directory.split('/')[:-1]) + '/'+x+'/',True))\r
+\r
+ if self.showFiles:\r
+ for x in files:\r
+ path = directory + x\r
+ name = x\r
+ if self.matchingPattern is not None:\r
+ if re.compile(self.matchingPattern).search(path):\r
+ self.list.append(self.getPictureEntryComponent(name,path ,False))\r
+ else:\r
+ pass \r
+ \r
+ self.l.setList(self.list)\r
+ \r
+ def canDescent(self):\r
+ return self.getSelection()[1]\r
+ \r
+ def descent(self):\r
+ self.changeDir(self.getSelection()[0])\r
+ \r
+ def getFilename(self):\r
+ return self.getSelection()[0].getPath()\r
+\r
+ def getServiceRef(self):\r
+ return self.getSelection()[0]\r
+\r
+ GUI_WIDGET = eListbox\r
+\r
+ def postWidgetCreate(self, instance):\r
+ instance.setContent(self.l)\r
+ instance.setItemHeight(23)\r
+ \r
+ def getPictureEntryComponent(self,name, absolute, isDir):\r
+ """ name={angezeigter Name}, absolute={vollstaendiger Pfad}, isDir={True,False} """\r
+ res = [ (absolute, isDir) ]\r
+ res.append((eListboxPythonMultiContent.TYPE_TEXT, 35, 1, 200, 20, 0, 0, name))\r
+ if isDir:\r
+ png = loadPNG("/usr/share/enigma2/extensions/directory.png")\r
+ else: \r
+ extension = name.split('.')\r
+ extension = extension[-1].lower()\r
+ if EXTENSIONS.has_key(extension):\r
+ png = loadPNG("/usr/share/enigma2/extensions/" + EXTENSIONS[extension] + ".png")\r
+ else:\r
+ png = None\r
+ if png is not None:\r
+ res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, 10, 2, 20, 20, png))\r
+ return res\r
+\r
+\r
+##################\r
+class XMLloader:\r
+ DEFAULT_NAMESPACES = (\r
+ None, # RSS 0.91, 0.92, 0.93, 0.94, 2.0\r
+ 'http://purl.org/rss/1.0/', # RSS 1.0\r
+ 'http://my.netscape.com/rdf/simple/0.9/' # RSS 0.90\r
+ )\r
+ DUBLIN_CORE = ('http://purl.org/dc/elements/1.1/',)\r
+ def getElementsByTagName( self, node, tagName, possibleNamespaces=DEFAULT_NAMESPACES ):\r
+ for namespace in possibleNamespaces:\r
+ children = node.getElementsByTagNameNS(namespace, tagName)\r
+ if len(children): return children\r
+ return []\r
+\r
+ def node_data( self, node, tagName, possibleNamespaces=DEFAULT_NAMESPACES):\r
+ children = self.getElementsByTagName(node, tagName, possibleNamespaces)\r
+ node = len(children) and children[0] or None\r
+ return node and "".join([child.data.encode("utf-8") for child in node.childNodes]) or None\r
+\r
+ def get_txt( self, node, tagName, default_txt="" ):\r
+ """\r
+ Liefert den Inhalt >tagName< des >node< zurueck, ist dieser nicht\r
+ vorhanden, wird >default_txt< zurueck gegeben.\r
+ """\r
+ return self.node_data( node, tagName ) or self.node_data( node, tagName, self.DUBLIN_CORE ) or default_txt\r
+\r
+ def getScreenXMLTitle( self,node ):\r
+ return self.get_txt( node, "name", "no title" )\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>
+<!-- I you have webcams that should be listed here, send an email to 3c5x9(at)gmx.net -->
+<xml>
+ <name>Mainmenu</name>
+ <menu>
+ <name>Webcam</name>
+ <menu>
+ <name>Amerika</name>
+ <menu>
+ <name>USA Westkueste</name>
+ <cam>
+ <name>Santa Monica Pier</name>
+ <url>http://www.westland.net/photo/file02.jpg</url>
+ </cam>
+ <cam>
+ <name>Venice Beach</name>
+ <url>http://www.westland.net/photo/file01.jpg</url>
+ </cam>
+ <cam>
+ <name>Pacific Palisades Bay</name>
+ <url>http://www.westland.net/photo/file01.jpg</url>
+ </cam>
+ <cam>
+ <name>Pacific Coast HWY</name>
+ <url>http://www.livinginthepalisades.com/photo/coastcam1.jpg</url>
+ </cam>
+ <cam>
+ <name>Auto Webcam - Live von unterwegs in L.A.</name>
+ <url>http://www.laavenue.com/la/la.jpg</url>
+ </cam>
+ <cam>
+ <name>sf Lawrence Hall of Science</name>
+ <url>http://sv.berkeley.edu/view/images/current_view.jpg</url>
+ </cam>
+ <cam>
+ <name>Mount St. Helens - VolcanoCam</name>
+ <url>http://www.fs.fed.us/gpnf/volcanocams/msh/images/mshvolcanocam.jpg</url>
+ </cam>
+ <cam>
+ <name>Seattle King 5 TV - From Queen Anne</name>
+ <url>http://www.king5.com/live/weather_images/external/queenanne_lg.jpg</url>
+ </cam>
+ <cam>
+ <name>Grand Canyon</name>
+ <url>http://www2.nature.nps.gov/air/WebCams/parks/grcacam/grca.jpg</url>
+ </cam>
+ <cam>
+ <name>Point Reyes National Seashore</name>
+ <url>http://www2.nature.nps.gov/air/webcams/parks/porecam/pore.jpg</url>
+ </cam>
+ </menu>
+ <menu>
+ <name>New York</name>
+ <cam>
+ <name>Broadway</name>
+ <url>http://images.earthcam.com/ec_metros/ourcams/charleyo.jpg</url>
+ </cam>
+ <cam>
+ <name>Ground zero</name>
+ <url>http://images.earthcam.com/ec_metros/ourcams/millenium.jpg</url>
+ </cam>
+ <cam>
+ <name>46th Street and Broadway</name>
+ <url>http://209.178.198.74/ec_metros/ourcams/fridays.jpg</url>
+ </cam>
+ <cam>
+ <name>Emipre State Building</name>
+ <url>http://www.nyvibe.net/nyvibescam/view.jpg</url>
+ </cam>
+ </menu>
+ <menu>
+ <name>Las Vegas</name>
+ <cam>
+ <name>MGM</name>
+ <url>http://images.earthcam.com/ec_metros/ourcams/mgm.jpg</url>
+ </cam>
+ <cam>
+ <name>Wedding Chapel</name>
+ <url>http://images.earthcam.com/ec_metros/ourcams/wedding.jpg</url>
+ </cam>
+ <cam>
+ <name>Paris Hotel</name>
+ <url>http://images.earthcam.com/ec_metros/ourcams/paris.jpg</url>
+ </cam>
+ <cam>
+ <name>Hard Rock Hotel</name>
+ <url>http://images.earthcam.com/ec_metros/ourcams/cafe.jpg</url>
+ </cam>
+ </menu>
+ <menu>
+ <name>Rio de Janeiro</name>
+ <cam>
+ <name>Lapa</name>
+ <url>http://transito.rio.rj.gov.br/imagens1/41.jpg</url>
+ </cam>
+ <cam>
+ <name>Av. Rio Branco / Av. Presidente Vargas</name>
+ <url>http://transito.rio.rj.gov.br/imagens1/2.jpg</url>
+ </cam>
+ <cam>
+ <name>Aterro do Flamengo</name>
+ <url>http://transito.rio.rj.gov.br/imagens1/5.jpg</url>
+ </cam>
+ <cam>
+ <name>Flamengo / Botafogo</name>
+ <url>http://transito.rio.rj.gov.br/imagens1/20.jpg</url>
+ </cam>
+ <cam>
+ <name>Copacabana - Avenida Atlantica</name>
+ <url>http://transito.rio.rj.gov.br/imagens1/26.jpg</url>
+ </cam>
+ <cam>
+ <name>Av. Nossa Senhora de Copacabana</name>
+ <url>http://transito.rio.rj.gov.br/imagens1/24.jpg</url>
+ </cam>
+ </menu>
+ <cam>
+ <name>Vancouver, English Bay</name>
+ <url>http://www.katkam.ca/p.asp?what=currentjpg</url>
+ </cam>
+ <cam>
+ <name>Torronto</name>
+ <url>http://www.traveloffice.ca/webcam/capture1.jpg</url>
+ </cam>
+ <cam>
+ <name>Argentinien, Mar del Plata</name>
+ <url>http://www.mardelplatawebcam.com.ar/img/webcam_colon_y_costa.jpg</url>
+ </cam>
+
+ </menu>
+ <menu>
+ <name>Europa</name>
+ <cam>
+ <name>London, Trafalgar Square</name>
+ <url>http://images.earthcam.com/ec_metros/ourcams/trafalgarsq.jpg</url>
+ </cam>
+ <cam>
+ <name>London, Big Ben</name>
+ <url>http://images.earthcam.com/ec_metros/ourcams/big_ben.jpg</url>
+ </cam>
+ <cam>
+ <name>London, Covent Garden</name>
+ <url>http://images.earthcam.com/ec_metros/ourcams/ltm.jpg</url>
+ </cam>
+ <cam>
+ <name>Spanien, Costa Brava</name>
+ <url>http://www.costabrava.cc/calella_live_webcam.jpg</url>
+ </cam>
+ <cam>
+ <name>Paris</name>
+ <url>http://www.abcparislive.com/eiffel2.jpg</url>
+ </cam>
+ <cam>
+ <name>Madrid</name>
+ <url>http://www.multimadrid.com/plaza.jpg</url>
+ </cam>
+ <cam>
+ <name>Dublin</name>
+ <url>http://www.ireland.com/includes/webcam/liveview.jpg</url>
+ </cam>
+ <cam>
+ <name>Griechenland, Naxos</name>
+ <url>http://www.flisvos-sportclub.com/images/webcam.jpg</url>
+ </cam>
+ <cam>
+ <name>Griechenland, Mykonos</name>
+ <url>http://www.travel-to-mykonos.com/webcam/1/mykonos.jpg</url>
+ </cam>
+ </menu>
+ <menu>
+ <name>Deutschland</name>
+ <menu>
+ <name>Hamburg</name>
+ <cam>
+ <name>Hamburg A7 Elbtunnel</name>
+ <url>http://www.ikk-hamburg.de/seiten/webcam/bild.php?bild=gross</url>
+ </cam>
+ <cam>
+ <name>Hamburg Landungsbruecken</name>
+ <url>http://www.dwd.de/scripts/getimg.php?src=/wundk/wkam1-10148.jpg</url>
+ </cam>
+ <cam>
+ <name>Hamburg Hafen</name>
+ <url>http://www.hafen-hamburg.de/webcam/camstill.jpg</url>
+ </cam>
+ </menu>
+ <menu>
+ <name>Dresden</name>
+ <cam>
+ <name>Frauenkirche</name>
+ <url>http://www3.mdr.de/webcams/frauen.jpg?t=12679</url>
+ </cam>
+ <cam>
+ <name>Blick auf Altstadtpanorama, Synagoge und Frauenkirche</name>
+ <url>http://www3.mdr.de/webcams/altstadt.jpg</url>
+ </cam>
+ <cam>
+ <name>Zwinger</name>
+ <url>http://www.softed.de/Webcam/webcam/hugesize.jpg</url>
+ </cam>
+ <cam>
+ <name>Fernsehturm</name>
+ <url>http://www.eb-world.de/FernsehturmCam/pics/Fernsehturm.jpg</url>
+ </cam>
+ <cam>
+ <name>Seidnitz</name>
+ <url>http://www.webcam.maxg.ath.cx/capture1.jpg</url>
+ </cam>
+ <cam>
+ <name>Blick zur Frauenkirche</name>
+ <url>http://dataware.de/~combase/fkdrv/images/campics/image.jpg</url>
+ </cam>
+ </menu>
+ <cam>
+ <name>Eutin</name>
+ <url>http://www.stadtwerke-eutin.de/webcam/images/wasserturm.jpg</url>
+ </cam>
+ <cam>
+ <name>Offenbach/Frankfurt</name>
+ <url>http://www.dwd.de/scripts/getimg.php?src=/wundk/wkam1-10640.jpg</url>
+ </cam>
+ <cam>
+ <name>St. Peter Ording</name>
+ <url>http://www.dwd.de/scripts/getimg.php?src=/wundk/wkam1-10028.jpg</url>
+ </cam>
+ <cam>
+ <name>Rostock-Warnemuende Seestrasse</name>
+ <url>http://www.dwd.de/scripts/getimg.php?src=/wundk/wkam1-10170.jpg</url>
+ </cam>
+ <cam>
+ <name>Kahler Asten - Wetterstation</name>
+ <url>http://www.dwd.de/scripts/getimg.php?src=/wundk/wkam1-10427.jpg</url>
+ </cam>
+ <cam>
+ <name>Braunlage</name>
+ <url>http://www.dwd.de/scripts/getimg.php?src=/wundk/wkam1-10452.jpg</url>
+ </cam>
+ <cam>
+ <name>Hannover</name>
+ <url>http://www.langelaube2.de/webcam/webcam.jpg</url>
+ </cam>
+ <cam>
+ <name>Koeln</name>
+ <url>http://www.wdr.de/themen/global/webcams/domcam/domcam_live.jpg</url>
+ </cam>
+ <cam>
+ <name>Frankfurt</name>
+ <url>http://www.frankfurt.de/sis/frankfurtbilder/cams/pia/images/webcam_pia.jpg</url>
+ </cam>
+ <cam>
+ <name>Berlin</name>
+ <url>http://www.dhm.de/webcams/pics/cam1_large.jpg</url>
+ </cam>
+ <cam>
+ <name>Berlin2</name>
+ <url>http://www.dwd.de/scripts/getimg.php?src=/wundk/wkam1-10384.jpg</url>
+ </cam>
+ <cam>
+ <name>Berlin, Museumsinsel</name>
+ <url>http://www.ipb.de/webcam/cam/cam.jpg</url>
+ </cam>
+ <cam>
+ <name>Leipzig</name>
+ <url>http://www.na-klarmann.de/cam.JPG</url>
+ </cam>
+ </menu>
+ <cam>
+ <name>Antarkits,South Georgia</name>
+ <url>http://www.sgisland.org/webcam/webcam.jpg</url>
+ </cam>
+ <cam>
+ <name>Neuseeland, Hammer Springs</name>
+ <url>http://www.hanmer.co.nz/hanmer.jpg</url>
+ </cam>
+ </menu>
+ <menu>
+ <name>Wetter</name>
+ <cam>
+ <name>Deutschlandwetter</name>
+ <url>http://www.dwd.de/scripts/getimg.php?src=/wundk/Wetter.jpg</url>
+ </cam>
+ <cam>
+ <name>Satellitenbild Wolken Deutschland</name>
+ <url>http://www.dwd.de/scripts/getimg.php?src=/hobbymet/mvvs1200.jpg</url>
+ </cam>
+ <cam>
+ <name>Satellitenbild Wolken Welt</name>
+ <url>http://www.dwd.de/scripts/getimg.php?src=/hobbymet/wvds1200.jpg</url>
+ </cam>
+ <cam>
+ <name>Wasser Temperaturen</name>
+ <url>http://www.dwd.de/scripts/getimg.php?src=/wundk/00-awg_sst.png</url>
+ </cam>
+ </menu>
+</xml>
\ No newline at end of file