3ab3907d33ddbaf07c335ee766c75f9c934fabdc
[enigma2.git] / lib / python / Plugins / Extensions / ZappingAlternatives / plugin.py
1 from enigma import *
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
19
20 import os
21
22 alternatives = {}
23
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)
31
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]
39                 
40 def loadAlternatives():
41         doc = xml.dom.minidom.parse(resolveFilename(SCOPE_CONFIG, "alternatives.xml"))
42         
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)
49
50 def sortKey(x):
51         return str.lower(ServiceReference(x).getServiceName().strip())
52                         
53 class AlternativeZapping(Screen):
54         skin = """
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" />
62                 </screen>"""
63         def __init__(self, session):
64                 self.skin = AlternativeZapping.skin
65                 Screen.__init__(self, session)
66
67                 self.filename = resolveFilename(SCOPE_CONFIG, "alternatives.xml")
68                 
69                 self.red = Label("")
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
75                 self.blue = Label("")
76                 self["blue"] = self.blue
77                 
78                 self.alternatives = {}
79                 
80                 self.serviceslist = []
81                 self.alternativeslist = []
82                 
83                 try:
84                         self.loadAlternatives()
85                 except:
86                         pass
87                 self["serviceslist"] = MenuList(self.serviceslist)
88                 self["alternativeslist"] = MenuList(self.alternativeslist)
89
90                 self.onShown.append(self.updateServices)
91                 self.onShown.append(self.updateAlternatives)
92
93                 self["actions"] = ActionMap(["DirectionActions", "OkCancelActions", "ColorActions"],
94                 {
95                         "ok": self.go,
96                         "cancel": self.go,
97                         "up": self.up,
98                         "down": self.down,
99                         "left": self.left,
100                         "right": self.right,
101                         "red": self.redKey,
102                         "green": self.greenKey,
103                         "yellow": self.yellowKey,
104                         "blue": self.blueKey,
105                 }, -1)
106                 
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"))
112                 
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))
124                                 t.appendChild(l)
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")
131                 doc.writexml(file)
132                 file.write("\n")
133                 file.close()
134         
135         def loadAlternatives(self):
136                 self.alternatives = {}
137                 alternatives = {}
138                 doc = xml.dom.minidom.parse(self.filename)
139                 
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)
149                 
150         def go(self):
151                 self.saveAlternatives()
152                 self.close()
153         
154         def up(self):
155                 self["serviceslist"].instance.moveSelection(self["serviceslist"].instance.moveUp)
156                 self.updateAlternatives()
157                 
158         def down(self):
159                 self["serviceslist"].instance.moveSelection(self["serviceslist"].instance.moveDown)
160                 self.updateAlternatives()
161         
162         def left(self):
163                 pass
164         
165         def right(self):
166                 pass
167         
168         def redKey(self):
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()
175         
176         def finishedAlternativeSelection(self, args):
177                 self.alternatives[self["serviceslist"].getCurrent()[1]].append(str(ServiceReference(args)))
178                 addAlternative(self["serviceslist"].getCurrent()[1], str(ServiceReference(args)))
179                 self.updateAlternatives()
180         
181         def updateServices(self):
182                 self.serviceslist = []
183                 keys = self.alternatives.keys()
184                 keys.sort(key = sortKey)
185                 for x in keys:
186                         self.serviceslist.append((ServiceReference(x).getServiceName(), x))
187                         
188                 self["serviceslist"].setList(self.serviceslist)
189                 if len(self.serviceslist) > 0:
190                         self.yellow.setText(_("Add alternative"))
191                         self.red.setText(_("Remove service"))
192                 else:
193                         self.yellow.setText("")
194                         self.red.setText("")
195         
196         def selectService(self, ref):
197                 count = 0
198                 for x in self["serviceslist"].list:
199                         if x[1] == ref:
200                                 self["serviceslist"].instance.moveSelectionTo(count)
201                                 return
202                         count += 1
203                         
204                         
205         def updateAlternatives(self):
206                 self.alternativeslist = []
207         
208                 if len(self.serviceslist) > 0:
209                         alternativelist = self.alternatives[self["serviceslist"].getCurrent()[1]]
210
211                         for x in alternativelist:
212                                 self.alternativeslist.append((ServiceReference(x).getServiceName(), x))
213                         
214                 self["alternativeslist"].setList(self.alternativeslist)
215                         
216         def greenKey(self):
217                 self.session.openWithCallback(self.finishedChannelSelection, SimpleChannelSelection, _("Select reference service"))
218
219         def finishedChannelSelection(self, *args):
220                 if len(args):
221                         serviceString = str(ServiceReference(args))
222                         if not self.alternatives.has_key(serviceString):
223                                 self.alternatives[serviceString] = []
224                         self.updateServices()
225                         self.selectService(serviceString)
226                         self.updateAlternatives()
227                 
228         def yellowKey(self):
229                 if len(self.serviceslist) > 0:
230                         self.session.openWithCallback(self.finishedAlternativeSelection, SimpleChannelSelection, _("Select alternative service"))
231         
232         def blueKey(self):
233                 pass
234
235
236 oldPlayService = None
237
238 from Components.PerServiceDisplay import PerServiceDisplay
239
240 class ServiceChanged(PerServiceDisplay):
241         def __init__(self, navcore):
242                 PerServiceDisplay.__init__(self, navcore,
243                         {
244                                 iPlayableService.evTuneFailed: self.tuneFailed,
245                                 iPlayableService.evStart: self.start
246                         })
247                 
248                 self.lastPlayAction = None
249                 self.nextPlayTry = 0
250
251         def start(self):
252 #               print "+++++++++++++++++++++++++++++++++++++++++++++++++Start", self.lastPlayAction
253                 if self.lastPlayAction is not None:
254                         self.lastPlayAction = None
255
256         def tuneFailed(self):
257 #               print "+++++++++++++++++++++++++++++++++++++++++++++++++Tuning failed!", self.lastPlayAction
258                 ref = self.lastPlayAction
259 #               print "Ref:", ref
260 #               print "Alternatives: failed to play service"
261                 if ref is not None:
262                         if alternatives.has_key(ref):
263 #                                       print "Alternatives: trying alternatives"
264                                         if len(alternatives[ref]) > self.nextPlayTry:
265 #                                               print "Alternatives: trying alternative", alternatives[ref][self.nextPlayTry]
266                                                 if oldPlayService(ServiceReference(alternatives[ref][self.nextPlayTry]).ref) == 0:
267                                                                 self.nextPlayTry += 1
268 #                                                               print "Alternatives: Alternative found!"
269                                                 else:
270                                                                 self.nextPlayTry += 1
271 #                                                               print "Alternatives: Alternative doesn't play either"
272                                                                 self.tuneFailed()
273                                         else:
274                                                 self.lastPlayAction = None
275
276                                         #print "Alternatives: No playable alternative found!"
277
278 servicechanged = None
279
280 def playService(self, ref):
281         #print "--------------------Alternatives: trying to play service", str(ServiceReference(ref))
282         if ref is not None:
283                 servicechanged.lastPlayAction = str(ServiceReference(ref))
284         servicechanged.nextPlayTry = 0
285         result = oldPlayService(ref)
286         
287         return result
288
289 def sessionstart(reason, session, **kwargs):
290         if reason == 0:
291                 try:
292                         loadAlternatives()
293                 except: # FIXME, THIS IS ILLEGAL CODE AND WILL BE PROSECUTED!
294                         pass
295                 
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)
301
302 def AlternativeZappingSetup(session, **kwargs):
303         session.open(AlternativeZapping)
304
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)]