plugin api change: Plugins() and main functions must receive (and possibly ignore...
[vuplus_dvbapp] / 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                 serviceString = str(ServiceReference(args))
221                 if not self.alternatives.has_key(serviceString):
222                         self.alternatives[serviceString] = []
223                 self.updateServices()
224                 self.selectService(serviceString)
225                 self.updateAlternatives()
226                 
227         def yellowKey(self):
228                 if len(self.serviceslist) > 0:
229                         self.session.openWithCallback(self.finishedAlternativeSelection, SimpleChannelSelection, _("Select alternative service"))
230         
231         def blueKey(self):
232                 pass
233
234
235 oldPlayService = NavigationInstance.instance.playService
236
237 from Components.PerServiceDisplay import PerServiceDisplay
238
239 class ServiceChanged(PerServiceDisplay):
240         def __init__(self, navcore):
241                 PerServiceDisplay.__init__(self, navcore,
242                         {
243                                 iPlayableService.evTuneFailed: self.tuneFailed,
244                                 iPlayableService.evStart: self.start
245                         })
246                 
247                 self.lastPlayAction = None
248                 self.nextPlayTry = 0
249
250         def start(self):
251 #               print "+++++++++++++++++++++++++++++++++++++++++++++++++Start", self.lastPlayAction
252                 if self.lastPlayAction is not None:
253                         self.lastPlayAction = None
254
255         def tuneFailed(self):
256 #               print "+++++++++++++++++++++++++++++++++++++++++++++++++Tuning failed!", self.lastPlayAction
257                 ref = self.lastPlayAction
258 #               print "Ref:", ref
259 #               print "Alternatives: failed to play service"
260                 if ref is not None:
261                         if alternatives.has_key(ref):
262 #                                       print "Alternatives: trying alternatives"
263                                         if len(alternatives[ref]) > self.nextPlayTry:
264 #                                               print "Alternatives: trying alternative", alternatives[ref][self.nextPlayTry]
265                                                 if oldPlayService(ServiceReference(alternatives[ref][self.nextPlayTry]).ref) == 0:
266                                                                 self.nextPlayTry += 1
267 #                                                               print "Alternatives: Alternative found!"
268                                                 else:
269                                                                 self.nextPlayTry += 1
270 #                                                               print "Alternatives: Alternative doesn't play either"
271                                                                 self.tuneFailed()
272                                         else:
273                                                 self.lastPlayAction = None
274
275                                         #print "Alternatives: No playable alternative found!"
276
277 servicechanged = ServiceChanged(NavigationInstance.instance)
278
279 def playService(self, ref):
280         #print "--------------------Alternatives: trying to play service", str(ServiceReference(ref))
281         servicechanged.lastPlayAction = str(ServiceReference(ref))
282         servicechanged.nextPlayTry = 0
283         result = oldPlayService(ref)
284
285         
286         return result
287
288 def autostart(reason):
289         if reason == 0:
290                 try:
291                         loadAlternatives()
292                 except:
293                         pass
294                 NavigationInstance.instance.playService = type(NavigationInstance.instance.playService)(playService, NavigationInstance, Navigation)
295                 
296
297 def AlternativeZappingSetup(session, **kwargs):
298         session.open(AlternativeZapping)
299
300 def Plugins(**kwargs):
301         return [PluginDescriptor(where = PluginDescriptor.WHERE_AUTOSTART, fnc = autostart),
302                         PluginDescriptor(name="Alternative services setup" , description="Defines alternatives for services.", where = PluginDescriptor.WHERE_PLUGINMENU, fnc=AlternativeZappingSetup)]