--- /dev/null
+Package: enigma2-plugin-extensions-dreammediathek
+Version: 20110131
+Description: Play rtp Stream on your Dreambox
+Maintainer: nixkoenner@newnigma2.to
+Homepage: http://www.newnigma2.to
+Depends: enigma2 (>> 2.6git20090409), twisted-web
--- /dev/null
+SUBDIRS = src
--- /dev/null
+All Files of this Software are licensed under the Creative Commons
+Attribution-NonCommercial-ShareAlike 3.0 Unported
+License if not stated otherwise in a files head. To view a copy of this license, visit
+http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter to Creative
+Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.
+
+Alternatively, this plugin may be distributed and executed on hardware which
+is licensed by Dream Multimedia GmbH.
+
+This plugin is NOT free software. It is open source, you are allowed to
+modify it (if you keep the license), but it may not be commercially
+distributed other than under the conditions noted above.
--- /dev/null
+installdir = $(libdir)/enigma2/python/Plugins/Extensions/dreamMediathek
+install_PYTHON = *.py
+install_DATA = *.png LICENSE maintainer.info *.xml
--- /dev/null
+# -*- coding: UTF-8 -*-
+from Plugins.Plugin import PluginDescriptor
+from Tools.BoundFunction import boundFunction
+from Screens.MessageBox import MessageBox
+from Screens.Screen import Screen
+from Screens.ChoiceBox import ChoiceBox
+from Components.ActionMap import ActionMap, NumberActionMap
+from Components.Sources.StaticText import StaticText
+from Components.Sources.List import List
+from Components.AVSwitch import AVSwitch
+from Components.config import config, Config, ConfigSelection, ConfigSubsection, ConfigText, getConfigListEntry, ConfigYesNo, ConfigIP, ConfigNumber,ConfigLocations
+from Components.config import KEY_DELETE, KEY_BACKSPACE, KEY_LEFT, KEY_RIGHT, KEY_HOME, KEY_END, KEY_TOGGLEOW, KEY_ASCII, KEY_TIMEOUT
+from Components.ConfigList import ConfigListScreen
+from Components.ServiceEventTracker import ServiceEventTracker, InfoBarBase
+
+from Tools.Directories import pathExists, fileExists, resolveFilename, SCOPE_PLUGINS, SCOPE_SKIN_IMAGE, SCOPE_HDD, SCOPE_CURRENT_PLUGIN, SCOPE_CURRENT_SKIN
+from Tools.LoadPixmap import LoadPixmap
+from enigma import eTimer, quitMainloop,eListbox,ePoint, RT_HALIGN_LEFT, RT_HALIGN_RIGHT, RT_VALIGN_CENTER, eListboxPythonMultiContent, eListbox, gFont, getDesktop, ePicLoad, eServiceCenter, iServiceInformation, eServiceReference,iSeekableService,iServiceInformation, iPlayableService, iPlayableServicePtr
+from os import path as os_path, system as os_system, unlink, stat, mkdir, popen, makedirs, listdir, access, rename, remove, W_OK, R_OK, F_OK
+from twisted.web import client
+from twisted.internet import reactor
+from time import time
+
+from Screens.InfoBarGenerics import InfoBarShowHide, InfoBarSeek, InfoBarNotifications, InfoBarServiceNotifications
+
+from ServiceXML import iWebTVStations
+
+config.plugins.dreamMediathek = ConfigSubsection()
+config.plugins.dreamMediathek.general = ConfigSubsection()
+config.plugins.dreamMediathek.general.on_movie_stop = ConfigSelection(default = "ask", choices = [
+ ("ask", _("Ask user")), ("quit", _("Return to movie list")), ("playnext", _("Play next video")), ("playagain", _("Play video again")) ])
+config.plugins.dreamMediathek.general.on_exit = ConfigSelection(default = "ask", choices = [
+ ("ask", _("Ask user")), ("quit", _("Return to movie list"))])
+
+
+class dreamMediathekPlayer(Screen, InfoBarNotifications):
+ STATE_IDLE = 0
+ STATE_PLAYING = 1
+ STATE_PAUSED = 2
+ ENABLE_RESUME_SUPPORT = True
+ ALLOW_SUSPEND = True
+
+ skin = """<screen name="dreamMediathekPlayer" flags="wfNoBorder" position="0,380" size="720,160" title="dreamMediathekPlayer" backgroundColor="transparent">
+ <ePixmap position="0,0" pixmap="skin_default/info-bg_mp.png" zPosition="-1" size="720,160" />
+ <ePixmap position="29,40" pixmap="skin_default/screws_mp.png" size="665,104" alphatest="on" />
+ <ePixmap position="48,70" pixmap="skin_default/icons/mp_buttons.png" size="108,13" alphatest="on" />
+ <ePixmap pixmap="skin_default/icons/icon_event.png" position="207,78" size="15,10" alphatest="on" />
+ <widget source="session.CurrentService" render="Label" position="230,73" size="360,40" font="Regular;20" backgroundColor="#263c59" shadowColor="#1d354c" shadowOffset="-1,-1" transparent="1">
+ <convert type="ServiceName">Name</convert>
+ </widget>
+ <widget source="session.CurrentService" render="Label" position="580,73" size="90,24" font="Regular;20" halign="right" backgroundColor="#4e5a74" transparent="1">
+ <convert type="ServicePosition">Length</convert>
+ </widget>
+ <widget source="session.CurrentService" render="Label" position="205,129" size="100,20" font="Regular;18" halign="center" valign="center" backgroundColor="#06224f" shadowColor="#1d354c" shadowOffset="-1,-1" transparent="1">
+ <convert type="ServicePosition">Position</convert>
+ </widget>
+ <widget source="session.CurrentService" render="PositionGauge" position="300,133" size="270,10" zPosition="2" pointer="skin_default/position_pointer.png:540,0" transparent="1" foregroundColor="#20224f">
+ <convert type="ServicePosition">Gauge</convert>
+ </widget>
+ <widget source="session.CurrentService" render="Label" position="576,129" size="100,20" font="Regular;18" halign="center" valign="center" backgroundColor="#06224f" shadowColor="#1d354c" shadowOffset="-1,-1" transparent="1">
+ <convert type="ServicePosition">Remaining</convert>
+ </widget>
+ </screen>"""
+
+ def __init__(self, session, service, lastservice, infoCallback = None, nextCallback = None, prevCallback = None):
+ Screen.__init__(self, session)
+ InfoBarNotifications.__init__(self)
+ self.session = session
+ self.service = service
+ self.infoCallback = infoCallback
+ self.nextCallback = nextCallback
+ self.prevCallback = prevCallback
+ self.screen_timeout = 5000
+ self.nextservice = None
+
+ print "evEOF=%d" % iPlayableService.evEOF
+ self.__event_tracker = ServiceEventTracker(screen = self, eventmap =
+ {
+ iPlayableService.evSeekableStatusChanged: self.__seekableStatusChanged,
+ iPlayableService.evStart: self.__serviceStarted,
+ iPlayableService.evEOF: self.__evEOF,
+ })
+
+ self["actions"] = ActionMap(["OkCancelActions", "InfobarSeekActions", "MediaPlayerActions", "MovieSelectionActions"],
+ {
+ "ok": self.ok,
+ "cancel": self.leavePlayer,
+ "stop": self.leavePlayer,
+ "playpauseService": self.playpauseService,
+ "seekFwd": self.playNextFile,
+ "seekBack": self.playPrevFile,
+ "showEventInfo": self.showVideoInfo,
+ }, -2)
+
+
+ self.lastservice = lastservice
+
+ self.hidetimer = eTimer()
+ self.hidetimer.timeout.get().append(self.ok)
+ self.returning = False
+
+ self.state = self.STATE_PLAYING
+ self.lastseekstate = self.STATE_PLAYING
+
+ self.onPlayStateChanged = [ ]
+ self.__seekableStatusChanged()
+
+ self.play()
+ self.onClose.append(self.__onClose)
+
+ def __onClose(self):
+ self.session.nav.stopService()
+
+ def __evEOF(self):
+ print "evEOF=%d" % iPlayableService.evEOF
+ print "Event EOF"
+ self.handleLeave(config.plugins.dreamMediathek.general.on_movie_stop.value)
+
+ def __setHideTimer(self):
+ self.hidetimer.start(self.screen_timeout)
+
+ def showInfobar(self):
+ self.show()
+ if self.state == self.STATE_PLAYING:
+ self.__setHideTimer()
+ else:
+ pass
+
+ def hideInfobar(self):
+ self.hide()
+ self.hidetimer.stop()
+
+ def ok(self):
+ if self.shown:
+ self.hideInfobar()
+ else:
+ self.showInfobar()
+
+ def showVideoInfo(self):
+ if self.shown:
+ self.hideInfobar()
+ if self.infoCallback is not None:
+ self.infoCallback()
+
+
+ def playNextFile(self):
+ print "playNextFile"
+ if self.nextCallback() is not None:
+ nextservice,error = self.nextCallback()
+ print "nextservice--->",nextservice
+ if nextservice is None:
+ self.handleLeave(config.plugins.dreamMediathek.general.on_movie_stop.value, error)
+ else:
+ self.playService(nextservice)
+ self.showInfobar()
+
+ def playPrevFile(self):
+ print "playPrevFile"
+ if self.prevCallback() is not None:
+ prevservice,error = self.prevCallback()
+ if prevservice is None:
+ self.handleLeave(config.plugins.dreamMediathek.general.on_movie_stop.value, error)
+ else:
+ self.playService(prevservice)
+ self.showInfobar()
+
+ def playagain(self):
+ print "playagain"
+ if self.state != self.STATE_IDLE:
+ self.stopCurrent()
+ self.play()
+
+ def playService(self, newservice):
+ if self.state != self.STATE_IDLE:
+ self.stopCurrent()
+ self.service = newservice
+ self.play()
+
+ def play(self):
+ if self.state == self.STATE_PAUSED:
+ if self.shown:
+ self.__setHideTimer()
+ self.state = self.STATE_PLAYING
+ self.session.nav.playService(self.service)
+ if self.shown:
+ self.__setHideTimer()
+
+ def stopCurrent(self):
+ print "stopCurrent"
+ self.session.nav.stopService()
+ self.state = self.STATE_IDLE
+
+ def playpauseService(self):
+ print "playpauseService"
+ if self.state == self.STATE_PLAYING:
+ self.pauseService()
+ elif self.state == self.STATE_PAUSED:
+ self.unPauseService()
+
+ def pauseService(self):
+ print "pauseService"
+ if self.state == self.STATE_PLAYING:
+ self.setSeekState(self.STATE_PAUSED)
+
+ def unPauseService(self):
+ print "unPauseService"
+ if self.state == self.STATE_PAUSED:
+ self.setSeekState(self.STATE_PLAYING)
+
+
+ def getSeek(self):
+ service = self.session.nav.getCurrentService()
+ if service is None:
+ return None
+
+ seek = service.seek()
+
+ if seek is None or not seek.isCurrentlySeekable():
+ return None
+
+ return seek
+
+ def isSeekable(self):
+ if self.getSeek() is None:
+ return False
+ return True
+
+ def __seekableStatusChanged(self):
+ print "seekable status changed!"
+ if not self.isSeekable():
+ self.setSeekState(self.STATE_PLAYING)
+ else:
+ print "seekable"
+
+ def __serviceStarted(self):
+ self.state = self.STATE_PLAYING
+ self.__seekableStatusChanged()
+
+ def setSeekState(self, wantstate):
+ print "setSeekState"
+ if wantstate == self.STATE_PAUSED:
+ print "trying to switch to Pause- state:",self.STATE_PAUSED
+ elif wantstate == self.STATE_PLAYING:
+ print "trying to switch to playing- state:",self.STATE_PLAYING
+ service = self.session.nav.getCurrentService()
+ if service is None:
+ print "No Service found"
+ return False
+ pauseable = service.pause()
+ if pauseable is None:
+ print "not pauseable."
+ self.state = self.STATE_PLAYING
+
+ if pauseable is not None:
+ print "service is pausable"
+ if wantstate == self.STATE_PAUSED:
+ print "WANT TO PAUSE"
+ pauseable.pause()
+ self.state = self.STATE_PAUSED
+ if not self.shown:
+ self.hidetimer.stop()
+ self.show()
+ elif wantstate == self.STATE_PLAYING:
+ print "WANT TO PLAY"
+ pauseable.unpause()
+ self.state = self.STATE_PLAYING
+ if self.shown:
+ self.__setHideTimer()
+
+ for c in self.onPlayStateChanged:
+ c(self.state)
+
+ return True
+
+ def handleLeave(self, how, error = False):
+ self.is_closing = True
+ if how == "ask":
+ list = (
+ (_("Yes"), "quit"),
+ (_("No, but play video again"), "playagain"),
+ (_("Yes, but play next video"), "playnext"),
+ (_("Yes, but play previous video"), "playprev"),
+ )
+ if error is False:
+ self.session.openWithCallback(self.leavePlayerConfirmed, ChoiceBox, title=_("Stop playing this movie?"), list = list)
+ else:
+ self.session.openWithCallback(self.leavePlayerConfirmed, ChoiceBox, title=_("No playable video found! Stop playing this movie?"), list = list)
+ else:
+ self.leavePlayerConfirmed([True, how])
+
+ def leavePlayer(self):
+ self.handleLeave(config.plugins.dreamMediathek.general.on_movie_stop.value)
+
+ def leavePlayerConfirmed(self, answer):
+ answer = answer and answer[1]
+ if answer == "quit":
+ self.close()
+ elif answer == "playnext":
+ self.playNextFile()
+ elif answer == "playprev":
+ self.playPrevFile()
+ elif answer == "playagain":
+ self.playagain()
+
+ def doEofInternal(self, playing):
+ if not self.execing:
+ return
+ if not playing :
+ return
+ self.handleLeave(config.usage.on_movie_eof.value)
+
--- /dev/null
+# -*- coding: utf-8 -*-
+from re import compile as re_compile
+from os import path as os_path, symlink, listdir, unlink, readlink, remove
+
+from xml.etree.cElementTree import parse as cet_parse
+from Tools.Directories import pathExists, fileExists, resolveFilename, SCOPE_PLUGINS, SCOPE_SKIN_IMAGE, SCOPE_HDD, SCOPE_CURRENT_PLUGIN, SCOPE_CURRENT_SKIN
+#WEBTV_STATIONS = "/etc/enigma2/webtv_stations.xml"
+WEBTV_STATIONS = resolveFilename(SCOPE_CURRENT_PLUGIN, "Extensions/dreamMediathek/webtv_stations.xml")
+
+class WebTVStations():
+ """Manages WebTVStations declared in a XML-Document."""
+ def __init__(self):
+ print "[WebTVStations] INIT"
+ self.webtv_stations = {}
+
+ def getWebTVStations(self, callback = None):
+ webtv_stations = []
+ self.webtv_stations = {}
+
+ if not os_path.exists(WEBTV_STATIONS):
+ return
+ tree = cet_parse(WEBTV_STATIONS).getroot()
+
+ def getValue(definitions, default):
+ ret = ""
+ Len = len(definitions)
+ return Len > 0 and definitions[Len-1].text or default
+
+ for tvstation in tree.findall("tvstation"):
+ data = { 'provider': None, 'title': None, 'streamurl': None }
+ try:
+ data['provider'] = getValue(tvstation.findall("provider"), False).encode("UTF-8")
+ data['title'] = getValue(tvstation.findall("title"), False).encode("UTF-8")
+ data['streamurl'] = getValue(tvstation.findall("streamurl"), False).encode("UTF-8")
+
+ print "TVSTATION--->",data
+ self.webtv_stations[data['title']] = data
+ except Exception, e:
+ print "[WebTVStations] Error reading Stations:", e
+
+ def getWebTVStationsList(self):
+ return sorted(self.webtv_stations.iterkeys())
+
+iWebTVStations = WebTVStations()
+
--- /dev/null
+nixkoenner@newnigma2.to\r
+dreamMediathek\r
--- /dev/null
+from Plugins.Plugin import PluginDescriptor
+from Tools.BoundFunction import boundFunction
+from Screens.MessageBox import MessageBox
+from Screens.Screen import Screen
+from Screens.ChoiceBox import ChoiceBox
+from Components.ActionMap import ActionMap, NumberActionMap
+from Components.Sources.StaticText import StaticText
+from Components.Sources.List import List
+from Components.AVSwitch import AVSwitch
+from Components.config import config, Config, ConfigSelection, ConfigSubsection, ConfigText, getConfigListEntry, ConfigYesNo, ConfigIP, ConfigNumber,ConfigLocations
+from Components.config import KEY_DELETE, KEY_BACKSPACE, KEY_LEFT, KEY_RIGHT, KEY_HOME, KEY_END, KEY_TOGGLEOW, KEY_ASCII, KEY_TIMEOUT
+from Components.ConfigList import ConfigListScreen
+from Components.ServiceEventTracker import ServiceEventTracker, InfoBarBase
+
+from Tools.Directories import pathExists, fileExists, resolveFilename, SCOPE_PLUGINS, SCOPE_SKIN_IMAGE, SCOPE_HDD, SCOPE_CURRENT_PLUGIN, SCOPE_CURRENT_SKIN
+from Tools.LoadPixmap import LoadPixmap
+from enigma import eTimer, quitMainloop,eListbox,ePoint, RT_HALIGN_LEFT, RT_HALIGN_RIGHT, RT_VALIGN_CENTER, eListboxPythonMultiContent, eListbox, gFont, getDesktop, ePicLoad, eServiceCenter, iServiceInformation, eServiceReference,iSeekableService,iServiceInformation, iPlayableService, iPlayableServicePtr
+from os import path as os_path, system as os_system, unlink, stat, mkdir, popen, makedirs, listdir, access, rename, remove, W_OK, R_OK, F_OK
+from twisted.web import client
+from twisted.internet import reactor
+from time import time
+
+from Screens.InfoBarGenerics import InfoBarShowHide, InfoBarSeek, InfoBarNotifications, InfoBarServiceNotifications
+
+from ServiceXML import iWebTVStations
+from MoviePlayer import dreamMediathekPlayer
+
+config.plugins.dreamMediathek = ConfigSubsection()
+config.plugins.dreamMediathek.general = ConfigSubsection()
+config.plugins.dreamMediathek.general.on_movie_stop = ConfigSelection(default = "ask", choices = [
+ ("ask", _("Ask user")), ("quit", _("Return to movie list")), ("playnext", _("Play next video")), ("playagain", _("Play video again")) ])
+config.plugins.dreamMediathek.general.on_exit = ConfigSelection(default = "ask", choices = [
+ ("ask", _("Ask user")), ("quit", _("Return to movie list"))])
+
+
+class dreamMediathekStationsScreen(Screen):
+ Details = {}
+ skin = """
+ <screen name="dreamMediathekStationsScreen" position="center,center" size="560,440" title="dreamMediathekStationsScreen" >
+ <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
+ <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
+ <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" size="140,40" alphatest="on" />
+ <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" size="140,40" alphatest="on" />
+ <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" />
+ <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" />
+ <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" />
+ <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" />
+ <widget source="streamlist" render="Listbox" position="5,50" size="550,280" zPosition="1" scrollbarMode="showOnDemand" transparent="1" >
+ <convert type="TemplatedMultiContent">
+ {"templates":
+ {"default": (55,[
+ MultiContentEntryText(pos = (5, 1), size = (540, 28), font=2, flags = RT_HALIGN_LEFT | RT_VALIGN_TOP| RT_WRAP, text = 1), # provider, title, streamurl
+ MultiContentEntryText(pos = (5, 28), size = (540, 18), font=3, flags = RT_HALIGN_LEFT | RT_VALIGN_TOP| RT_WRAP, text = 0), # provider, title, streamurl
+ ]),
+ "state": (55,[
+ MultiContentEntryText(pos = (10, 1), size = (560, 28), font=2, flags = RT_HALIGN_LEFT | RT_VALIGN_TOP| RT_WRAP, text = 0), # index 0 is the name
+ MultiContentEntryText(pos = (10, 22), size = (560, 46), font=3, flags = RT_HALIGN_LEFT | RT_VALIGN_TOP| RT_WRAP, text = 1), # index 2 is the description
+ ])
+ },
+ "fonts": [gFont("Regular", 22),gFont("Regular", 18),gFont("Regular", 26),gFont("Regular", 20)],
+ "itemHeight": 55
+ }
+ </convert>
+ </widget>
+ </screen>"""
+
+ def __init__(self, session, skin_path = None):
+ Screen.__init__(self, session)
+ self.session = session
+ self.skin_path = skin_path
+ if self.skin_path == None:
+ self.skin_path = resolveFilename(SCOPE_CURRENT_PLUGIN, "Extensions/dreamMediathek")
+
+ self.lastservice = session.nav.getCurrentlyPlayingServiceReference()
+ self.streamlist = []
+ self.currentList = "streamlist"
+ self.oldList = None
+ self.tvstations = None
+
+ self["streamlist"] = List(self.streamlist)
+ self["key_red"] = StaticText(_("Cancel"))
+ self["key_green"] = StaticText(_("OK"))
+ self["key_yellow"] = StaticText()
+ self["key_blue"] = StaticText()
+
+ self["FredMainActions"] = ActionMap(["ShortcutActions", "WizardActions"],
+ {
+ "ok": self.keyOK,
+ "back": self.leavePlayer,
+ "red": self.leavePlayer,
+ }, -1)
+
+ #self["videoactions"].setEnabled(True)
+ self.onLayoutFinish.append(self.layoutFinished)
+ self.onShown.append(self.setWindowTitle)
+ self.onClose.append(self.__onClose)
+
+ def __onClose(self):
+ self.Details = {}
+ self.session.nav.playService(self.lastservice)
+
+ def layoutFinished(self):
+ self.currentList = "streamlist"
+ self.getStationsList()
+ #self["videoactions"].setEnabled(False)
+
+ def setWindowTitle(self):
+ self.setTitle(_("dreamMediathek TV Stations"))
+
+ def handleLeave(self, how):
+ self.is_closing = True
+ if how == "ask":
+ list = (
+ (_("Yes"), "quit"),
+ (_("No"), "continue")
+ )
+ self.session.openWithCallback(self.leavePlayerConfirmed, ChoiceBox, title=_("Really quit dreamMediathek ?"), list = list)
+ else:
+ self.leavePlayerConfirmed([True, how])
+
+ def leavePlayer(self):
+ print "leavePlayer"
+ self.handleLeave(config.plugins.dreamMediathek.general.on_exit.value)
+
+ def leavePlayerConfirmed(self, answer):
+ answer = answer and answer[1]
+ if answer == "quit":
+ self.doQuit()
+ else:
+ return
+
+ def doQuit(self):
+ config.plugins.dreamMediathek.general.save()
+ config.plugins.dreamMediathek.save()
+ self.close()
+
+ def keyOK(self):
+ print "self.currentList im KeyOK",self.currentList
+ if self.currentList == "streamlist":
+ current = self["streamlist"].getCurrent()
+ if current:
+ print current
+ url = current[2]
+ title = current[1]
+ myreference = eServiceReference(4097,0,url)
+ myreference.setName(title)
+ #self.session.open(dreamMediathekPlayer, myreference, self.lastservice, infoCallback = self.showVideoInfo, nextCallback = self.getNextEntry, prevCallback = self.getPrevEntry )
+ self.session.open(dreamMediathekPlayer, myreference, self.lastservice)
+
+ def getStationsList(self):
+ print "getStationsList"
+ iWebTVStations.getWebTVStations()
+ self.buildStationsList()
+
+ def buildStationsComponent(self, station):
+ provider = None
+ title = None
+ streamurl = None
+ if iWebTVStations.webtv_stations[station].has_key("provider"):
+ provider = iWebTVStations.webtv_stations[station]["provider"]
+ if iWebTVStations.webtv_stations[station].has_key("title"):
+ title = iWebTVStations.webtv_stations[station]["title"]
+ if iWebTVStations.webtv_stations[station].has_key("streamurl"):
+ streamurl = iWebTVStations.webtv_stations[station]["streamurl"]
+ return((provider, title, streamurl ))
+
+ def buildStationsList(self):
+ self.tvstations = None
+ self.tvstations = iWebTVStations.getWebTVStationsList()
+ if self.tvstations and len(self.tvstations):
+ self.streamlist = []
+ for station in self.tvstations:
+ print "GOT station:",station
+ self.streamlist.append(self.buildStationsComponent(station))
+ if len(self.streamlist):
+ self["streamlist"].setList(self.streamlist)
+ self["streamlist"].style = "default"
+
+def dreamMediathekMain(session, **kwargs):
+ session.open(dreamMediathekStationsScreen)
+
+
+def Plugins(path, **kwargs):
+ global plugin_path
+ plugin_path = path
+ return PluginDescriptor(
+ name=_("DreamMediathek"),
+ description=_("Play Web and ipTV streams"),
+ where = [ PluginDescriptor.WHERE_EXTENSIONSMENU, PluginDescriptor.WHERE_PLUGINMENU ],
+ fnc = dreamMediathekMain)
--- /dev/null
+<?xml version="1.0" ?>
+<webtvstations>
+ <tvstation>
+ <provider>americafree.tv</provider>
+ <title>AFTVHD</title>
+ <streamurl>rtsp://video1.americafree.tv/AFTVHDVarietyH2642000.sdp</streamurl>
+ </tvstation>
+ <tvstation>
+ <provider>cctv.ws</provider>
+ <title>VH1 Classic</title>
+ <streamurl>http://cctv.ws/1/ssic01/VH1classic</streamurl>
+ </tvstation>
+ <tvstation>
+ <provider>americafree.tv</provider>
+ <title>AFTVHDVariety</title>
+ <streamurl>rtsp://video1.americafree.tv/AFTVHDVarietyH2642000.sdp</streamurl>
+ </tvstation>
+</webtvstations>