2 from Screens.Screen import Screen
3 from Screens.MessageBox import MessageBox
4 from Components.ActionMap import ActionMap
5 from Components.Label import Label
6 from Components.Input import Input
7 from Components.GUIComponent import *
8 from Components.Pixmap import Pixmap
9 from Components.MenuList import MenuList
10 from Components.FileList import FileEntryComponent, FileList
11 from Navigation import Navigation
12 import NavigationInstance
13 from Screens.ChannelSelection import SimpleChannelSelection
14 from ServiceReference import ServiceReference
15 from Plugins.Plugin import PluginDescriptor
16 from Tools.Directories import resolveFilename, SCOPE_CONFIG
17 import xml.dom.minidom
18 from Tools.XMLTools import elementsWithTag
24 def addAlternative(service1, service2):
25 if not alternatives.has_key(service1):
26 alternatives[service1] = []
27 alternatives[service1].append(service2)
28 if not alternatives.has_key(service2):
29 alternatives[service2] = []
30 alternatives[service2].append(service1)
32 def removeAlternative(service1, service2):
33 alternatives[service1].remove(service2)
34 alternatives[service2].remove(service1)
35 if len(alternatives[service1]) == 0:
36 del alternatives[service1]
37 if len(alternatives[service2]) == 0:
38 del alternatives[service2]
40 def loadAlternatives():
41 doc = xml.dom.minidom.parse(resolveFilename(SCOPE_CONFIG, "alternatives.xml"))
43 root = doc.childNodes[0]
44 for service in elementsWithTag(root.childNodes, 'service'):
45 newService = str(service.getAttribute('ref'))
46 for alternative in elementsWithTag(service.childNodes, 'alternative'):
47 newAlternative = str(alternative.getAttribute('ref'))
48 addAlternative(newService, newAlternative)
51 return str.lower(ServiceReference(x).getServiceName().strip())
53 class AlternativeZapping(Screen):
55 <screen position="100,100" size="560,400" title="Services alternatives setup..." >
56 <widget name="red" position="0,0" size="140,40" backgroundColor="red" halign="center" valign="center" font="Regular;21" />
57 <widget name="green" position="140,0" size="140,40" backgroundColor="green" halign="center" valign="center" font="Regular;21" />
58 <widget name="yellow" position="280,0" size="140,40" backgroundColor="yellow" halign="center" valign="center" font="Regular;21" />
59 <widget name="blue" position="420,0" size="140,40" backgroundColor="blue" halign="center" valign="center" font="Regular;21" />
60 <widget name="serviceslist" position="0,40" size="280,360" scrollbarMode="showOnDemand" />
61 <widget name="alternativeslist" position="280,40" size="280,360" selectionDisabled="1" scrollbarMode="showOnDemand" />
63 def __init__(self, session):
64 self.skin = AlternativeZapping.skin
65 Screen.__init__(self, session)
67 self.filename = resolveFilename(SCOPE_CONFIG, "alternatives.xml")
70 self["red"] = self.red
71 self.green = Label(_("Add service"))
72 self["green"] = self.green
73 self.yellow = Label("")
74 self["yellow"] = self.yellow
76 self["blue"] = self.blue
78 self.alternatives = {}
80 self.serviceslist = []
81 self.alternativeslist = []
84 self.loadAlternatives()
87 self["serviceslist"] = MenuList(self.serviceslist)
88 self["alternativeslist"] = MenuList(self.alternativeslist)
90 self.onShown.append(self.updateServices)
91 self.onShown.append(self.updateAlternatives)
93 self["actions"] = ActionMap(["DirectionActions", "OkCancelActions", "ColorActions"],
102 "green": self.greenKey,
103 "yellow": self.yellowKey,
104 "blue": self.blueKey,
107 def saveAlternatives(self):
108 doc = xml.dom.minidom.Document()
109 root_element = doc.createElement('alternatives')
110 doc.appendChild(root_element)
111 root_element.appendChild(doc.createTextNode("\n"))
113 for alternative in self.alternatives.keys():
114 t = doc.createTextNode("\t")
115 root_element.appendChild(t)
116 t = doc.createElement('service')
117 t.setAttribute("ref", alternative)
118 root_element.appendChild(t)
119 t.appendChild(doc.createTextNode("\n"))
120 for x in self.alternatives[alternative]:
121 t.appendChild(doc.createTextNode("\t\t"))
122 l = doc.createElement('alternative')
123 l.setAttribute("ref", str(x))
125 t.appendChild(doc.createTextNode("\n"))
126 t.appendChild(doc.createTextNode("\t"))
127 root_element.appendChild(t)
128 t = doc.createTextNode("\n")
129 root_element.appendChild(t)
130 file = open(self.filename, "w")
135 def loadAlternatives(self):
136 self.alternatives = {}
138 doc = xml.dom.minidom.parse(self.filename)
140 root = doc.childNodes[0]
141 for service in elementsWithTag(root.childNodes, 'service'):
142 newService = str(service.getAttribute('ref'))
143 if not self.alternatives.has_key(newService):
144 self.alternatives[newService] = []
145 for alternative in elementsWithTag(service.childNodes, 'alternative'):
146 newAlternative = str(alternative.getAttribute('ref'))
147 self.alternatives[newService].append(newAlternative)
148 addAlternative(newService, newAlternative)
151 self.saveAlternatives()
155 self["serviceslist"].instance.moveSelection(self["serviceslist"].instance.moveUp)
156 self.updateAlternatives()
159 self["serviceslist"].instance.moveSelection(self["serviceslist"].instance.moveDown)
160 self.updateAlternatives()
169 for x in self.alternatives[self["serviceslist"].getCurrent()[1]]:
170 removeAlternative(self["serviceslist"].getCurrent()[1], x)
171 if len(self.serviceslist) > 0:
172 del self.alternatives[self["serviceslist"].getCurrent()[1]]
173 self.updateServices()
174 self.updateAlternatives()
176 def finishedAlternativeSelection(self, *args):
178 self.alternatives[self["serviceslist"].getCurrent()[1]].append(str(ServiceReference(args)))
179 addAlternative(self["serviceslist"].getCurrent()[1], str(ServiceReference(args)))
180 self.updateAlternatives()
182 def updateServices(self):
183 self.serviceslist = []
184 keys = self.alternatives.keys()
185 keys.sort(key = sortKey)
187 self.serviceslist.append((ServiceReference(x).getServiceName(), x))
189 self["serviceslist"].setList(self.serviceslist)
190 if len(self.serviceslist) > 0:
191 self.yellow.setText(_("Add alternative"))
192 self.red.setText(_("Remove service"))
194 self.yellow.setText("")
197 def selectService(self, ref):
199 for x in self["serviceslist"].list:
201 self["serviceslist"].instance.moveSelectionTo(count)
206 def updateAlternatives(self):
207 self.alternativeslist = []
209 if len(self.serviceslist) > 0:
210 alternativelist = self.alternatives[self["serviceslist"].getCurrent()[1]]
212 for x in alternativelist:
213 self.alternativeslist.append((ServiceReference(x).getServiceName(), x))
215 self["alternativeslist"].setList(self.alternativeslist)
218 self.session.openWithCallback(self.finishedChannelSelection, SimpleChannelSelection, _("Select reference service"))
220 def finishedChannelSelection(self, *args):
222 serviceString = str(ServiceReference(args[0]))
223 if not self.alternatives.has_key(serviceString):
224 self.alternatives[serviceString] = []
225 self.updateServices()
226 self.selectService(serviceString)
227 self.updateAlternatives()
230 if len(self.serviceslist) > 0:
231 self.session.openWithCallback(self.finishedAlternativeSelection, SimpleChannelSelection, _("Select alternative service"))
237 oldPlayService = None
239 from Components.PerServiceDisplay import PerServiceDisplay
241 class ServiceChanged(PerServiceDisplay):
242 def __init__(self, navcore):
243 PerServiceDisplay.__init__(self, navcore,
245 iPlayableService.evTuneFailed: self.tuneFailed,
246 iPlayableService.evStart: self.start
249 self.lastPlayAction = None
253 # print "+++++++++++++++++++++++++++++++++++++++++++++++++Start", self.lastPlayAction
254 if self.lastPlayAction is not None:
255 self.lastPlayAction = None
257 def tuneFailed(self):
258 # print "+++++++++++++++++++++++++++++++++++++++++++++++++Tuning failed!", self.lastPlayAction
259 ref = self.lastPlayAction
261 # print "Alternatives: failed to play service"
263 if alternatives.has_key(ref):
264 # print "Alternatives: trying alternatives"
265 if len(alternatives[ref]) > self.nextPlayTry:
266 # print "Alternatives: trying alternative", alternatives[ref][self.nextPlayTry]
267 if oldPlayService(ServiceReference(alternatives[ref][self.nextPlayTry]).ref) == 0:
268 self.nextPlayTry += 1
269 # print "Alternatives: Alternative found!"
271 self.nextPlayTry += 1
272 # print "Alternatives: Alternative doesn't play either"
275 self.lastPlayAction = None
277 #print "Alternatives: No playable alternative found!"
279 servicechanged = None
281 def playService(self, ref, **kwargs):
282 #print "--------------------Alternatives: trying to play service", str(ServiceReference(ref))
284 servicechanged.lastPlayAction = str(ServiceReference(ref))
285 servicechanged.nextPlayTry = 0
286 result = oldPlayService(ref, **kwargs)
289 def sessionstart(reason, session, **kwargs):
293 except: # FIXME, THIS IS ILLEGAL CODE AND WILL BE PROSECUTED!
296 # attach to this sessions navigation instance.
297 global oldPlayService, servicechanged
298 oldPlayService = session.nav.playService
299 session.nav.playService = type(session.nav.playService)(playService, NavigationInstance, Navigation)
300 servicechanged = ServiceChanged(session.nav)
302 def AlternativeZappingSetup(session, **kwargs):
303 session.open(AlternativeZapping)
305 def Plugins(**kwargs):
306 return [PluginDescriptor(where = PluginDescriptor.WHERE_SESSIONSTART, fnc = sessionstart),
307 PluginDescriptor(name="Alternative services setup" , description="Defines alternatives for services.", where = PluginDescriptor.WHERE_PLUGINMENU, fnc=AlternativeZappingSetup)]