fix getBouquetList
[enigma2.git] / lib / python / Screens / ChannelSelection.py
1 from Screen import Screen
2 from Components.Button import Button
3 from Components.ServiceList import ServiceList
4 from Components.ActionMap import NumberActionMap, ActionMap
5 from Components.MenuList import MenuList
6 from EpgSelection import EPGSelection
7 from enigma import eServiceReference, eEPGCache, eServiceCenter, eServiceCenterPtr, iMutableServiceListPtr, iStaticServiceInformationPtr, eTimer, eDVBDB
8 from Components.config import config, ConfigSubsection, ConfigText
9 from Screens.FixedMenu import FixedMenu
10 from Tools.NumericalTextInput import NumericalTextInput
11 from Components.NimManager import nimmanager
12 from Components.Sources.Clock import Clock
13 from Components.Input import Input
14 from Components.ParentalControl import parentalControl
15 from Screens.InputBox import InputBox, PinInput
16 from Screens.MessageBox import MessageBox
17 from ServiceReference import ServiceReference
18 from Tools.BoundFunction import boundFunction
19 from re import *
20 from os import remove
21
22 FLAG_SERVICE_NEW_FOUND = 64 #define in lib/dvb/idvb.h as dxNewFound = 64
23
24 import xml.dom.minidom
25
26 class BouquetSelector(Screen):
27         def __init__(self, session, bouquets, selectedFunc, enableWrapAround=False):
28                 Screen.__init__(self, session)
29
30                 self.selectedFunc=selectedFunc
31
32                 self["actions"] = ActionMap(["OkCancelActions"],
33                         {
34                                 "ok": self.okbuttonClick,
35                                 "cancel": self.cancelClick
36                         })
37                 entrys = [ ]
38                 for x in bouquets:
39                         entrys.append((x[0], x[1]))
40                 self["menu"] = MenuList(entrys, enableWrapAround)
41
42         def getCurrent(self):
43                 cur = self["menu"].getCurrent()
44                 return cur and cur[1]
45
46         def okbuttonClick(self):
47                 self.selectedFunc(self.getCurrent())
48
49         def up(self):
50                 self["menu"].up()
51
52         def down(self):
53                 self["menu"].down()
54
55         def cancelClick(self):
56                 self.close(False)
57
58 class ChannelContextMenu(Screen):
59         def __init__(self, session, csel):
60                 Screen.__init__(self, session)
61                 self.csel = csel
62                 self.bsel = None
63
64                 self["actions"] = ActionMap(["OkCancelActions"],
65                         {
66                                 "ok": self.okbuttonClick,
67                                 "cancel": self.cancelClick
68                         })
69                 menu = [ ]
70
71                 current_root = csel.getRoot()
72                 current_sel_path = csel.getCurrentSelection().getPath()
73                 current_sel_flags = csel.getCurrentSelection().flags
74                 inBouquetRootList = current_root and current_root.getPath().find('FROM BOUQUET "bouquets.') != -1 #FIXME HACK
75                 inBouquet = csel.getMutableList() is not None
76                 haveBouquets = config.usage.multibouquet.value
77
78                 if not csel.bouquet_mark_edit and not csel.movemode:
79                         if not inBouquetRootList:
80                                 if (csel.getCurrentSelection().flags & eServiceReference.flagDirectory) != eServiceReference.flagDirectory:
81                                         if config.ParentalControl.configured.value:
82                                                 if parentalControl.getProtectionLevel(csel.getCurrentSelection().toCompareString()) == -1:
83                                                         menu.append((_("add to parental protection"), boundFunction(self.addParentalProtection, csel.getCurrentSelection())))
84                                                 else:
85                                                         menu.append((_("remove from parental protection"), boundFunction(self.removeParentalProtection, csel.getCurrentSelection())))
86                                         if haveBouquets:
87                                                 menu.append((_("add service to bouquet"), self.addServiceToBouquetSelected))
88                                         else:
89                                                 menu.append((_("add service to favourites"), self.addServiceToBouquetSelected))
90                                 else:
91                                         if haveBouquets:
92                                                 if not inBouquet and current_sel_path.find("PROVIDERS") == -1:
93                                                         menu.append((_("copy to favourites"), self.copyCurrentToBouquetList))
94                                         if current_sel_path.find("flags == %d" %(FLAG_SERVICE_NEW_FOUND)) != -1:
95                                                 menu.append((_("remove all new found flags"), self.removeAllNewFoundFlags))
96                                 if inBouquet:
97                                         menu.append((_("remove entry"), self.removeCurrentService))
98                                 if current_root is not None and current_root.getPath().find("flags == %d" %(FLAG_SERVICE_NEW_FOUND)) != -1:
99                                         menu.append((_("remove new found flag"), self.removeNewFoundFlag))
100                         else:
101                                         menu.append((_("add bouquet"), self.showBouquetInputBox))
102                                         menu.append((_("remove entry"), self.removeBouquet))
103
104                 if inBouquet: # current list is editable?
105                         if not csel.bouquet_mark_edit:
106                                 if not csel.movemode:
107                                         menu.append((_("add marker"), self.showMarkerInputBox))
108                                         menu.append((_("enable move mode"), self.toggleMoveMode))
109                                         if not inBouquetRootList:
110                                                 if haveBouquets:
111                                                         menu.append((_("enable bouquet edit"), self.bouquetMarkStart))
112                                                 else:
113                                                         menu.append((_("enable favourite edit"), self.bouquetMarkStart))
114                                 else:
115                                         menu.append((_("disable move mode"), self.toggleMoveMode))
116                         elif not inBouquetRootList:
117                                 if haveBouquets:
118                                         menu.append((_("end bouquet edit"), self.bouquetMarkEnd))
119                                         menu.append((_("abort bouquet edit"), self.bouquetMarkAbort))
120                                 else:
121                                         menu.append((_("end favourites edit"), self.bouquetMarkEnd))
122                                         menu.append((_("abort favourites edit"), self.bouquetMarkAbort))
123
124                 menu.append((_("back"), self.cancelClick))
125                 self["menu"] = MenuList(menu)
126
127         def okbuttonClick(self):
128                 self["menu"].getCurrent()[1]()
129
130         def cancelClick(self):
131                 self.close(False)
132                 
133         def showBouquetInputBox(self):
134                 self.session.openWithCallback(self.bouquetInputCallback, InputBox, title=_("Please enter a name for the new bouquet"), text="bouquetname", maxSize=False, type=Input.TEXT)
135
136         def bouquetInputCallback(self, bouquet):
137                 if bouquet is not None:
138                         self.csel.addBouquet(bouquet, None)
139                 self.close()
140
141         def addParentalProtection(self, service):
142                 parentalControl.protectService(service.toCompareString())
143                 self.close()
144
145         def removeParentalProtection(self, service):
146                 self.session.openWithCallback(boundFunction(self.pinEntered, service.toCompareString()), PinInput, pinList = [config.ParentalControl.servicepin[0].value], triesEntry = config.ParentalControl.retries.servicepin, title = _("Enter the service pin"), windowTitle = _("Change pin code"))
147
148         def pinEntered(self, service, result):
149                 if result:
150                         parentalControl.unProtectService(service)
151                         self.close()
152                 else:
153                         self.session.openWithCallback(self.close, MessageBox, _("The pin code you entered is wrong."), MessageBox.TYPE_ERROR)
154
155         def addServiceToBouquetSelected(self):
156                 bouquets = self.csel.getBouquetList()
157                 if bouquets is None:
158                         cnt = 0
159                 else:
160                         cnt = len(bouquets)
161                 if cnt > 1: # show bouquet list
162                         self.bsel = self.session.openWithCallback(self.bouquetSelClosed, BouquetSelector, bouquets, self.addCurrentServiceToBouquet)
163                 elif cnt == 1: # add to only one existing bouquet
164                         self.addCurrentServiceToBouquet(bouquets[0][1])
165
166         def bouquetSelClosed(self, recursive):
167                 self.bsel = None
168                 if recursive:
169                         self.close(False)
170
171         def copyCurrentToBouquetList(self):
172                 self.csel.copyCurrentToBouquetList()
173                 self.close()
174
175         def removeBouquet(self):
176                 self.csel.removeBouquet()
177                 self.close()
178
179         def showMarkerInputBox(self):
180                 self.session.openWithCallback(self.markerInputCallback, InputBox, title=_("Please enter a name for the new marker"), text="markername", maxSize=False, type=Input.TEXT)
181
182         def markerInputCallback(self, marker):
183                 if marker is not None:
184                         self.csel.addMarker(marker)
185                 self.close()
186
187         def addCurrentServiceToBouquet(self, dest):
188                 self.csel.addCurrentServiceToBouquet(dest)
189                 if self.bsel is not None:
190                         self.bsel.close(True)
191                 else:
192                         self.close(True) # close bouquet selection
193
194         def removeCurrentService(self):
195                 self.csel.removeCurrentService()
196                 self.close()
197
198         def toggleMoveMode(self):
199                 self.csel.toggleMoveMode()
200                 self.close()
201
202         def bouquetMarkStart(self):
203                 self.csel.startMarkedEdit()
204                 self.close()
205
206         def bouquetMarkEnd(self):
207                 self.csel.endMarkedEdit(abort=False)
208                 self.close()
209
210         def bouquetMarkAbort(self):
211                 self.csel.endMarkedEdit(abort=True)
212                 self.close()
213
214         def removeNewFoundFlag(self):
215                 eDVBDB.getInstance().removeFlag(self.csel.getCurrentSelection(), FLAG_SERVICE_NEW_FOUND)
216                 self.close()
217
218         def removeAllNewFoundFlags(self):
219                 curpath = self.csel.getCurrentSelection().getPath()
220                 idx = curpath.find("satellitePosition == ")
221                 if idx != -1:
222                         tmp = curpath[idx+21:]
223                         idx = tmp.find(')')
224                         if idx != -1:
225                                 satpos = int(tmp[:idx])
226                                 eDVBDB.getInstance().removeFlags(FLAG_SERVICE_NEW_FOUND, -1, -1, -1, satpos)
227                 self.close()
228
229 class ChannelSelectionEPG:
230         def __init__(self):
231                 self["ChannelSelectEPGActions"] = ActionMap(["ChannelSelectEPGActions"],
232                         {
233                                 "showEPGList": self.showEPGList,
234                         })
235
236         def showEPGList(self):
237                 ref=self.getCurrentSelection()
238                 ptr=eEPGCache.getInstance()
239                 if ptr.startTimeQuery(ref) != -1:
240                         self.session.open(EPGSelection, ref)
241                 else:
242                         print 'no epg for service', ref.toString()
243
244 class ChannelSelectionEdit:
245         def __init__(self):
246                 self.entry_marked = False
247                 self.movemode = False
248                 self.bouquet_mark_edit = False
249                 self.mutableList = None
250                 self.__marked = [ ]
251                 self.saved_title = None
252                 self.saved_root = None
253
254                 class ChannelSelectionEditActionMap(ActionMap):
255                         def __init__(self, csel, contexts = [ ], actions = { }, prio=0):
256                                 ActionMap.__init__(self, contexts, actions, prio)
257                                 self.csel = csel
258
259                         def action(self, contexts, action):
260                                 if action == "cancel":
261                                         self.csel.handleEditCancel()
262                                         return 0 # fall-trough
263                                 elif action == "ok":
264                                         return 0 # fall-trough
265                                 else:
266                                         return ActionMap.action(self, contexts, action)
267
268                 self["ChannelSelectEditActions"] = ChannelSelectionEditActionMap(self, ["ChannelSelectEditActions", "OkCancelActions"],
269                         {
270                                 "contextMenu": self.doContext,
271                         })
272
273         def getMutableList(self, root=eServiceReference()):
274                 if not self.mutableList is None:
275                         return self.mutableList
276                 serviceHandler = eServiceCenter.getInstance()
277                 if not root.valid():
278                         root=self.getRoot()
279                 list = root and serviceHandler.list(root)
280                 if list is not None:
281                         return list.startEdit()
282                 return None
283
284         def buildBouquetID(self, str):
285                 tmp = str.lower()
286                 name = ''
287                 for c in tmp:
288                         if (c >= 'a' and c <= 'z') or (c >= '0' and c <= '9'):
289                                 name += c
290                         else:
291                                 name += '_'
292                 return name
293
294         def addMarker(self, name):
295                 current = self.servicelist.getCurrent()
296                 mutableList = self.getMutableList()
297                 cnt = 0
298                 while mutableList:
299                         str = '1:64:%d:0:0:0:0:0:0:0::%s'%(cnt, name)
300                         ref = eServiceReference(str)
301                         if current and current.valid():
302                                 if not mutableList.addService(ref, current):
303                                         self.servicelist.addService(ref, True)
304                                         mutableList.flushChanges()
305                                         break
306                         elif not mutableList.addService(ref):
307                                 self.servicelist.addService(ref, True)
308                                 mutableList.flushChanges()
309                                 break
310                         cnt+=1
311
312         def addBouquet(self, bName, services):
313                 serviceHandler = eServiceCenter.getInstance()
314                 mutableBouquetList = serviceHandler.list(self.bouquet_root).startEdit()
315                 if mutableBouquetList:
316                         if self.mode == MODE_TV:
317                                 bName += " (TV)"
318                                 str = '1:7:1:0:0:0:0:0:0:0:(type == 1) FROM BOUQUET \"userbouquet.%s.tv\" ORDER BY bouquet'%(self.buildBouquetID(bName))
319                         else:
320                                 bName += " (Radio)"
321                                 str = '1:7:2:0:0:0:0:0:0:0:(type == 2) FROM BOUQUET \"userbouquet.%s.radio\" ORDER BY bouquet'%(self.buildBouquetID(bName))
322                         new_bouquet_ref = eServiceReference(str)
323                         if not mutableBouquetList.addService(new_bouquet_ref):
324                                 self.bouquetNumOffsetCache = { }
325                                 mutableBouquetList.flushChanges()
326                                 eDVBDB.getInstance().reloadBouquets()
327                                 mutableBouquet = serviceHandler.list(new_bouquet_ref).startEdit()
328                                 if mutableBouquet:
329                                         mutableBouquet.setListName(bName)
330                                         if services is not None:
331                                                 for service in services:
332                                                         if mutableBouquet.addService(service):
333                                                                 print "add", service.toString(), "to new bouquet failed"
334                                                         else:
335                                                                 current = self.servicelist.getCurrent()
336                                                                 if current and current.toString() == self.bouquet_rootstr:
337                                                                         self.servicelist.addService(service, True)
338                                         mutableBouquet.flushChanges()
339                                 else:
340                                         print "get mutable list for new created bouquet failed"
341                         else:
342                                 print "add", str, "to bouquets failed"
343                 else:
344                         print "bouquetlist is not editable"
345
346         def copyCurrentToBouquetList(self):
347                 provider = ServiceReference(self.getCurrentSelection())
348                 providerName = provider.getServiceName()
349                 serviceHandler = eServiceCenter.getInstance()
350                 services = serviceHandler.list(provider.ref)
351                 self.addBouquet(providerName, services and services.getContent('R', True))
352
353         def removeBouquet(self):
354                 refstr = self.getCurrentSelection().toString()
355                 self.bouquetNumOffsetCache = { }
356                 pos = refstr.find('FROM BOUQUET "')
357                 if pos != -1:
358                         refstr = refstr[pos+14:]
359                         pos = refstr.find('"')
360                         if pos != -1:
361                                 filename = '/etc/enigma2/' + refstr[:pos] # FIXMEEE !!! HARDCODED /etc/enigma2
362                 self.removeCurrentService()
363                 try:
364                         remove(filename)
365                 except OSError:
366                         print "error during remove of", filename
367
368 #  multiple marked entry stuff ( edit mode, later multiepg selection )
369         def startMarkedEdit(self):
370                 self.mutableList = self.getMutableList()
371                 # add all services from the current list to internal marked set in listboxservicecontent
372                 self.clearMarks() # this clears the internal marked set in the listboxservicecontent
373                 self.saved_title = self.instance.getTitle()
374                 pos = self.saved_title.find(')')
375                 new_title = self.saved_title[:pos+1]
376                 if config.usage.multibouquet.value:
377                         new_title += ' ' + _("[bouquet edit]")
378                 else:
379                         new_title += ' ' + _("[favourite edit]")
380                 self.setTitle(new_title)
381                 self.bouquet_mark_edit = True
382                 self.__marked = self.servicelist.getRootServices()
383                 for x in self.__marked:
384                         self.servicelist.addMarked(eServiceReference(x))
385                 self.savedPath = self.servicePath[:]
386                 self.showAllServices()
387
388         def endMarkedEdit(self, abort):
389                 if not abort and self.mutableList is not None:
390                         self.bouquetNumOffsetCache = { }
391                         new_marked = set(self.servicelist.getMarked())
392                         old_marked = set(self.__marked)
393                         removed = old_marked - new_marked
394                         added = new_marked - old_marked
395                         changed = False
396                         for x in removed:
397                                 changed = True
398                                 self.mutableList.removeService(eServiceReference(x))
399                         for x in added:
400                                 changed = True
401                                 self.mutableList.addService(eServiceReference(x))
402                         if changed:
403                                 self.mutableList.flushChanges()
404                 self.__marked = []
405                 self.clearMarks()
406                 self.bouquet_mark_edit = False
407                 self.mutableList = None
408                 self.setTitle(self.saved_title)
409                 self.saved_title = None
410                 # self.servicePath is just a reference to servicePathTv or Radio...
411                 # so we never ever do use the asignment operator in self.servicePath
412                 del self.servicePath[:] # remove all elements
413                 self.servicePath += self.savedPath # add saved elements
414                 del self.savedPath
415                 self.setRoot(self.servicePath[len(self.servicePath)-1])
416
417         def clearMarks(self):
418                 self.servicelist.clearMarks()
419
420         def doMark(self):
421                 ref = self.servicelist.getCurrent()
422                 if self.servicelist.isMarked(ref):
423                         self.servicelist.removeMarked(ref)
424                 else:
425                         self.servicelist.addMarked(ref)
426
427         def removeCurrentService(self):
428                 ref = self.servicelist.getCurrent()
429                 mutableList = self.getMutableList()
430                 if ref.valid() and mutableList is not None:
431                         if not mutableList.removeService(ref):
432                                 self.bouquetNumOffsetCache = { }
433                                 mutableList.flushChanges() #FIXME dont flush on each single removed service
434                                 self.servicelist.removeCurrent()
435
436         def addCurrentServiceToBouquet(self, dest):
437                 mutableList = self.getMutableList(dest)
438                 if not mutableList is None:
439                         if not mutableList.addService(self.servicelist.getCurrent()):
440                                 self.bouquetNumOffsetCache = { }
441                                 mutableList.flushChanges()
442
443         def toggleMoveMode(self):
444                 if self.movemode:
445                         if self.entry_marked:
446                                 self.toggleMoveMarked() # unmark current entry
447                         self.movemode = False
448                         self.pathChangedDisabled = False # re-enable path change
449                         self.mutableList.flushChanges() # FIXME add check if changes was made
450                         self.mutableList = None
451                         self.setTitle(self.saved_title)
452                         self.saved_title = None
453                         if self.getRoot() == self.bouquet_root:
454                                 self.bouquetNumOffsetCache = { }
455                 else:
456                         self.mutableList = self.getMutableList()
457                         self.movemode = True
458                         self.pathChangedDisabled = True # no path change allowed in movemode
459                         self.saved_title = self.instance.getTitle()
460                         new_title = self.saved_title
461                         pos = self.saved_title.find(')')
462                         new_title = self.saved_title[:pos+1] + ' ' + _("[move mode]") + self.saved_title[pos+1:]
463                         self.setTitle(new_title);
464
465         def handleEditCancel(self):
466                 if self.movemode: #movemode active?
467                         self.channelSelected() # unmark
468                         self.toggleMoveMode() # disable move mode
469                 elif self.bouquet_mark_edit:
470                         self.endMarkedEdit(True) # abort edit mode
471
472         def toggleMoveMarked(self):
473                 if self.entry_marked:
474                         self.servicelist.setCurrentMarked(False)
475                         self.entry_marked = False
476                 else:
477                         self.servicelist.setCurrentMarked(True)
478                         self.entry_marked = True
479
480         def doContext(self):
481                 self.session.open(ChannelContextMenu, self)
482
483 MODE_TV = 0
484 MODE_RADIO = 1
485
486 # this makes it much simple to implement a selectable radio or tv mode :)
487 service_types_tv = '1:7:1:0:0:0:0:0:0:0:(type == 1) || (type == 17) || (type == 195) || (type == 25)'
488 service_types_radio = '1:7:2:0:0:0:0:0:0:0:(type == 2)'
489
490 class ChannelSelectionBase(Screen):
491         def __init__(self, session):
492                 Screen.__init__(self, session)
493
494                 self["key_red"] = Button(_("All"))
495                 self["key_green"] = Button(_("Satellites"))
496                 self["key_yellow"] = Button(_("Provider"))
497                 self["key_blue"] = Button(_("Favourites"))
498
499                 self["list"] = ServiceList()
500                 self.servicelist = self["list"]
501
502                 self.numericalTextInput = NumericalTextInput()
503                 self.numericalTextInput.setUseableChars(u'1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ')
504
505                 self.servicePathTV = [ ]
506                 self.servicePathRadio = [ ]
507                 self.servicePath = [ ]
508
509                 self.mode = MODE_TV
510
511                 self.pathChangedDisabled = False
512
513                 self.bouquetNumOffsetCache = { }
514
515                 self["ChannelSelectBaseActions"] = NumberActionMap(["ChannelSelectBaseActions", "NumberActions"],
516                         {
517                                 "showFavourites": self.showFavourites,
518                                 "showAllServices": self.showAllServices,
519                                 "showProviders": self.showProviders,
520                                 "showSatellites": self.showSatellites,
521                                 "nextBouquet": self.nextBouquet,
522                                 "prevBouquet": self.prevBouquet,
523                                 "nextMarker": self.nextMarker,
524                                 "prevMarker": self.prevMarker,
525                                 "1": self.keyNumberGlobal,
526                                 "2": self.keyNumberGlobal,
527                                 "3": self.keyNumberGlobal,
528                                 "4": self.keyNumberGlobal,
529                                 "5": self.keyNumberGlobal,
530                                 "6": self.keyNumberGlobal,
531                                 "7": self.keyNumberGlobal,
532                                 "8": self.keyNumberGlobal,
533                                 "9": self.keyNumberGlobal,
534                                 "0": self.keyNumber0
535                         })
536                 self.recallBouquetMode()
537
538         def appendDVBTypes(self, ref):
539                 path = ref.getPath()
540                 pos = path.find(' FROM BOUQUET')
541                 if pos != -1:
542                         return eServiceReference(self.service_types + path[pos:])
543                 return ref
544
545         def getBouquetNumOffset(self, bouquet):
546                 if config.usage.multibouquet.value:
547                         return 0
548                 bouquet = self.appendDVBTypes(bouquet)
549                 try:
550                         return self.bouquetNumOffsetCache[bouquet.toString()]
551                 except:
552                         offsetCount = 0
553                         serviceHandler = eServiceCenter.getInstance()
554                         bouquetlist = serviceHandler.list(self.bouquet_root)
555                         if not bouquetlist is None:
556                                 while True:
557                                         bouquetIterator = self.appendDVBTypes(bouquetlist.getNext())
558                                         if not bouquetIterator.valid(): #end of list
559                                                 break
560                                         self.bouquetNumOffsetCache[bouquetIterator.toString()]=offsetCount
561                                         if ((bouquetIterator.flags & eServiceReference.flagDirectory) != eServiceReference.flagDirectory):
562                                                 continue
563                                         servicelist = serviceHandler.list(bouquetIterator)
564                                         if not servicelist is None:
565                                                 while True:
566                                                         serviceIterator = servicelist.getNext()
567                                                         if not serviceIterator.valid(): #check if end of list
568                                                                 break
569                                                         if serviceIterator.flags: #playable services have no flags
570                                                                 continue
571                                                         offsetCount += 1
572                 return self.bouquetNumOffsetCache.get(bouquet.toString(), offsetCount)
573
574         def recallBouquetMode(self):
575                 if self.mode == MODE_TV:
576                         self.service_types = service_types_tv
577                         if config.usage.multibouquet.value:
578                                 self.bouquet_rootstr = '1:7:1:0:0:0:0:0:0:0:(type == 1) FROM BOUQUET "bouquets.tv" ORDER BY bouquet'
579                         else:
580                                 self.bouquet_rootstr = '%s FROM BOUQUET "userbouquet.favourites.tv" ORDER BY bouquet'%(self.service_types)
581                 else:
582                         self.service_types = service_types_radio
583                         if config.usage.multibouquet.value:
584                                 self.bouquet_rootstr = '1:7:1:0:0:0:0:0:0:0:(type == 1) FROM BOUQUET "bouquets.radio" ORDER BY bouquet'
585                         else:
586                                 self.bouquet_rootstr = '%s FROM BOUQUET "userbouquet.favourites.radio" ORDER BY bouquet'%(self.service_types)
587                 self.bouquet_root = eServiceReference(self.bouquet_rootstr)
588
589         def setTvMode(self):
590                 self.mode = MODE_TV
591                 self.servicePath = self.servicePathTV
592                 self.recallBouquetMode()
593                 title = self.instance.getTitle()
594                 pos = title.find(" (")
595                 if pos != -1:
596                         title = title[:pos]
597                 title += " (TV)"
598                 self.setTitle(title)
599
600         def setRadioMode(self):
601                 self.mode = MODE_RADIO
602                 self.servicePath = self.servicePathRadio
603                 self.recallBouquetMode()
604                 title = self.instance.getTitle()
605                 pos = title.find(" (")
606                 if pos != -1:
607                         title = title[:pos]
608                 title += " (Radio)"
609                 self.setTitle(title)
610
611         def setRoot(self, root, justSet=False):
612                 path = root.getPath()
613                 inBouquetRootList = path.find('FROM BOUQUET "bouquets.') != -1 #FIXME HACK
614                 pos = path.find(' FROM BOUQUET')
615                 isBouquet = pos != -1
616                 if not inBouquetRootList and isBouquet:
617                         self.servicelist.setMode(ServiceList.MODE_FAVOURITES)
618                         self.servicelist.setNumberOffset(self.getBouquetNumOffset(root))
619                         refstr = self.service_types + path[pos:]
620                         root = eServiceReference(refstr)
621                 else:
622                         self.servicelist.setMode(ServiceList.MODE_NORMAL)
623                 self.servicelist.setRoot(root, justSet)
624                 self.buildTitleString()
625
626         def removeModeStr(self, str):
627                 if self.mode == MODE_TV:
628                         pos = str.find(' (TV)')
629                 else:
630                         pos = str.find(' (Radio)')
631                 if pos != -1:
632                         return str[:pos]
633                 return str
634
635         def getServiceName(self, ref):
636                 str = self.removeModeStr(ServiceReference(ref).getServiceName())
637                 if not len(str):
638                         pathstr = ref.getPath()
639                         if pathstr.find('FROM PROVIDERS') != -1:
640                                 return _("Provider")
641                         if pathstr.find('FROM SATELLITES') != -1:
642                                 return _("Satellites")
643                         if pathstr.find(') ORDER BY name') != -1:
644                                 return _("All")
645                 return str
646
647         def buildTitleString(self):
648                 titleStr = self.instance.getTitle()
649                 pos = titleStr.find(']')
650                 if pos == -1:
651                         pos = titleStr.find(')')
652                 if pos != -1:
653                         titleStr = titleStr[:pos+1]
654                         Len = len(self.servicePath)
655                         if Len > 0:
656                                 base_ref = self.servicePath[0]
657                                 if Len > 1:
658                                         end_ref = self.servicePath[Len-1]
659                                 else:
660                                         end_ref = None
661                                 nameStr = self.getServiceName(base_ref)
662                                 titleStr += ' ' + nameStr
663                                 if end_ref is not None:
664                                         if Len > 2:
665                                                 titleStr += '/../'
666                                         else:
667                                                 titleStr += '/'
668                                         nameStr = self.getServiceName(end_ref)
669                                         titleStr += nameStr
670                                 self.setTitle(titleStr)
671
672         def moveUp(self):
673                 self.servicelist.moveUp()
674
675         def moveDown(self):
676                 self.servicelist.moveDown()
677
678         def clearPath(self):
679                 del self.servicePath[:]
680
681         def enterPath(self, ref, justSet=False):
682                 self.servicePath.append(ref)
683                 self.setRoot(ref, justSet)
684
685         def pathUp(self, justSet=False):
686                 prev = self.servicePath.pop()
687                 length = len(self.servicePath)
688                 if length:
689                         current = self.servicePath[length-1]
690                         self.setRoot(current, justSet)
691                         if not justSet:
692                                 self.setCurrentSelection(prev)
693                 return prev
694
695         def isBasePathEqual(self, ref):
696                 if len(self.servicePath) > 1 and self.servicePath[0] == ref:
697                         return True
698                 return False
699
700         def isPrevPathEqual(self, ref):
701                 length = len(self.servicePath)
702                 if length > 1 and self.servicePath[length-2] == ref:
703                         return True
704                 return False
705
706         def preEnterPath(self, refstr):
707                 return False
708
709         def showAllServices(self):
710                 if not self.pathChangedDisabled:
711                         refstr = '%s ORDER BY name'%(self.service_types)
712                         if not self.preEnterPath(refstr):
713                                 ref = eServiceReference(refstr)
714                                 currentRoot = self.getRoot()
715                                 if currentRoot is None or currentRoot != ref:
716                                         self.clearPath()
717                                         self.enterPath(ref)
718
719         def showSatellites(self):
720                 if not self.pathChangedDisabled:
721                         refstr = '%s FROM SATELLITES ORDER BY satellitePosition'%(self.service_types)
722                         if not self.preEnterPath(refstr):
723                                 ref = eServiceReference(refstr)
724                                 justSet=False
725                                 prev = None
726
727                                 if self.isBasePathEqual(ref):
728                                         if self.isPrevPathEqual(ref):
729                                                 justSet=True
730                                         prev = self.pathUp(justSet)
731                                 else:
732                                         currentRoot = self.getRoot()
733                                         if currentRoot is None or currentRoot != ref:
734                                                 justSet=True
735                                                 self.clearPath()
736                                                 self.enterPath(ref, True)
737                                 if justSet:
738                                         serviceHandler = eServiceCenter.getInstance()
739                                         servicelist = serviceHandler.list(ref)
740                                         if not servicelist is None:
741                                                 while True:
742                                                         service = servicelist.getNext()
743                                                         if not service.valid(): #check if end of list
744                                                                 break
745                                                         orbpos = service.getUnsignedData(4) >> 16
746                                                         if service.getPath().find("FROM PROVIDER") != -1:
747                                                                 service_name = _("Providers")
748                                                         elif service.getPath().find("flags == %d" %(FLAG_SERVICE_NEW_FOUND)) != -1:
749                                                                 service_name = _("New")
750                                                         else:
751                                                                 service_name = _("Services")
752                                                         try:
753                                                                 service_name += str(' - %s'%(nimmanager.getSatDescription(orbpos)))
754                                                                 service.setName(service_name) # why we need this cast?
755                                                         except:
756                                                                 if orbpos == 0xFFFF: #Cable
757                                                                         n = ("%s (%s)") % (service_name, _("Cable"))
758                                                                 elif orbpos == 0xEEEE: #Terrestrial
759                                                                         n = ("%s (%s)") % (service_name, _("Terrestrial"))
760                                                                 else:
761                                                                         if orbpos > 1800: # west
762                                                                                 orbpos = 3600 - orbpos
763                                                                                 h = _("W")
764                                                                         else:
765                                                                                 h = _("E")
766                                                                         n = ("%s (%d.%d" + h + ")") % (service_name, orbpos / 10, orbpos % 10)
767                                                                 service.setName(n)
768                                                         self.servicelist.addService(service)
769                                                 self.servicelist.finishFill()
770                                                 if prev is not None:
771                                                         self.setCurrentSelection(prev)
772
773         def showProviders(self):
774                 if not self.pathChangedDisabled:
775                         refstr = '%s FROM PROVIDERS ORDER BY name'%(self.service_types)
776                         if not self.preEnterPath(refstr):
777                                 ref = eServiceReference(refstr)
778                                 if self.isBasePathEqual(ref):
779                                         self.pathUp()
780                                 else:
781                                         currentRoot = self.getRoot()
782                                         if currentRoot is None or currentRoot != ref:
783                                                 self.clearPath()
784                                                 self.enterPath(ref)
785
786         def changeBouquet(self, direction):
787                 if not self.pathChangedDisabled:
788                         if self.isBasePathEqual(self.bouquet_root):
789                                 self.pathUp()
790                                 if direction < 0:
791                                         self.moveUp()
792                                 else:
793                                         self.moveDown()
794                                 ref = self.getCurrentSelection()
795                                 self.enterPath(ref)
796
797         def inBouquet(self):
798                 return self.isBasePathEqual(self.bouquet_root)
799
800         def atBegin(self):
801                 return self.servicelist.atBegin()
802
803         def atEnd(self):
804                 return self.servicelist.atEnd()
805
806         def nextBouquet(self):
807                 self.changeBouquet(+1)
808
809         def prevBouquet(self):
810                 self.changeBouquet(-1)
811
812         def showFavourites(self):
813                 if not self.pathChangedDisabled:
814                         if not self.preEnterPath(self.bouquet_rootstr):
815                                 if self.isBasePathEqual(self.bouquet_root):
816                                         self.pathUp()
817                                 else:
818                                         currentRoot = self.getRoot()
819                                         if currentRoot is None or currentRoot != self.bouquet_root:
820                                                 self.clearPath()
821                                                 self.enterPath(self.bouquet_root)
822
823         def keyNumberGlobal(self, number):
824                 unichar = self.numericalTextInput.getKey(number)
825                 charstr = unichar.encode("utf-8")
826                 if len(charstr) == 1:
827                         self.servicelist.moveToChar(charstr[0])
828
829         def getRoot(self):
830                 return self.servicelist.getRoot()
831
832         def getCurrentSelection(self):
833                 return self.servicelist.getCurrent()
834
835         def setCurrentSelection(self, service):
836                 servicepath = service.getPath()
837                 pos = servicepath.find(" FROM BOUQUET")
838                 if pos != -1:
839                         if self.mode == MODE_TV:
840                                 servicepath = '(type == 1)' + servicepath[pos:]
841                         else:
842                                 servicepath = '(type == 2)' + servicepath[pos:]
843                         service.setPath(servicepath)
844                 self.servicelist.setCurrent(service)
845
846         def getBouquetList(self):
847                 bouquets = [ ]
848                 serviceHandler = eServiceCenter.getInstance()
849                 if config.usage.multibouquet.value:
850                         list = serviceHandler.list(self.bouquet_root)
851                         if not list is None:
852                                 while True:
853                                         s = list.getNext()
854                                         if not s.valid():
855                                                 break
856                                         if ((s.flags & eServiceReference.flagDirectory) == eServiceReference.flagDirectory):
857                                                 info = serviceHandler.info(s)
858                                                 if not info is None:
859                                                         bouquets.append((info.getName(s), s))
860                                 return bouquets
861                 else:
862                         info = serviceHandler.info(self.bouquet_root)
863                         if not info is None:
864                                 bouquets.append((info.getName(self.bouquet_root), self.bouquet_root))
865                         return bouquets
866                 return None
867
868         def keyNumber0(self, num):
869                 if len(self.servicePath) > 1:
870                         self.keyGoUp()
871                 else:
872                         self.keyNumberGlobal(num)
873
874         def keyGoUp(self):
875                 if len(self.servicePath) > 1:
876                         if self.isBasePathEqual(self.bouquet_root):
877                                 self.showFavourites()
878                         else:
879                                 ref = eServiceReference('%s FROM SATELLITES ORDER BY satellitePosition'%(self.service_types))
880                                 if self.isBasePathEqual(ref):
881                                         self.showSatellites()
882                                 else:
883                                         ref = eServiceReference('%s FROM PROVIDERS ORDER BY name'%(self.service_types))
884                                         if self.isBasePathEqual(ref):
885                                                 self.showProviders()
886                                         else:
887                                                 self.showAllServices()
888
889         def nextMarker(self):
890                 self.servicelist.moveToNextMarker()
891
892         def prevMarker(self):
893                 self.servicelist.moveToPrevMarker()
894
895 HISTORYSIZE = 20
896
897 #config for lastservice
898 config.tv = ConfigSubsection()
899 config.tv.lastservice = ConfigText()
900 config.tv.lastroot = ConfigText()
901 config.radio = ConfigSubsection()
902 config.radio.lastservice = ConfigText()
903 config.radio.lastroot = ConfigText()
904 config.servicelist = ConfigSubsection()
905 config.servicelist.lastmode = ConfigText(default = "tv")
906
907 class ChannelSelection(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelectionEPG):
908         def __init__(self, session):
909                 ChannelSelectionBase.__init__(self,session)
910                 ChannelSelectionEdit.__init__(self)
911                 ChannelSelectionEPG.__init__(self)
912
913                 self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"],
914                         {
915                                 "cancel": self.cancel,
916                                 "ok": self.channelSelected,
917                                 "keyRadio": self.setModeRadio,
918                                 "keyTV": self.setModeTv,
919                         })
920
921                 self.onShown.append(self.__onShown)
922
923                 self.lastChannelRootTimer = eTimer()
924                 self.lastChannelRootTimer.timeout.get().append(self.__onCreate)
925                 self.lastChannelRootTimer.start(100,True)
926
927                 self.history_tv = [ ]
928                 self.history_radio = [ ]
929                 self.history = self.history_tv
930                 self.history_pos = 0
931
932                 self.lastservice = config.tv.lastservice
933                 self.lastroot = config.tv.lastroot
934                 self.revertMode = None
935
936         def setMode(self):
937                 self.restoreRoot()
938                 lastservice=eServiceReference(self.lastservice.value)
939                 if lastservice.valid():
940                         self.setCurrentSelection(lastservice)
941
942         def setModeTv(self):
943                 if self.revertMode is None and config.servicelist.lastmode.value == "radio":
944                         self.revertMode = MODE_RADIO
945                 self.history = self.history_tv
946                 self.lastservice = config.tv.lastservice
947                 self.lastroot = config.tv.lastroot
948                 config.servicelist.lastmode.value = "tv"
949                 self.setTvMode()
950                 self.setMode()
951
952         def setModeRadio(self):
953                 if self.revertMode is None and config.servicelist.lastmode.value == "tv":
954                         self.revertMode = MODE_TV
955                 if config.usage.e1like_radio_mode.value:
956                         self.history = self.history_radio
957                         self.lastservice = config.radio.lastservice
958                         self.lastroot = config.radio.lastroot
959                         config.servicelist.lastmode.value = "radio"
960                         self.setRadioMode()
961                         self.setMode()
962
963         def __onCreate(self):
964                 if config.usage.e1like_radio_mode.value:
965                         if config.servicelist.lastmode.value == "tv":
966                                 self.setModeTv()
967                         else:
968                                 self.setModeRadio()
969                 else:
970                         self.setModeTv()
971                 lastservice=eServiceReference(self.lastservice.value)
972                 if lastservice.valid():
973                         self.zap()
974
975         def __onShown(self):
976                 self.recallBouquetMode()
977                 ref = self.session.nav.getCurrentlyPlayingServiceReference()
978                 if ref is not None and ref.valid() and ref.getPath() == "":
979                         self.servicelist.setPlayableIgnoreService(ref)
980                 else:
981                         self.servicelist.setPlayableIgnoreService(eServiceReference())
982
983         def channelSelected(self):
984                 ref = self.getCurrentSelection()
985                 if self.movemode:
986                         self.toggleMoveMarked()
987                 elif (ref.flags & 7) == 7:
988                         self.enterPath(ref)
989                 elif self.bouquet_mark_edit:
990                         self.doMark()
991                 elif not (ref.flags & 64): # no marker
992                         self.zap()
993                         self.close(ref)
994
995         #called from infoBar and channelSelected
996         def zap(self):
997                 self.revertMode=None
998                 ref = self.session.nav.getCurrentlyPlayingServiceReference()
999                 nref = self.getCurrentSelection()
1000                 if ref is None or ref != nref:
1001                         self.session.nav.playService(nref)
1002                         self.saveRoot()
1003                         self.saveChannel()
1004                         config.servicelist.lastmode.save()
1005                         self.addToHistory(nref)
1006
1007         def addToHistory(self, ref):
1008                 if self.servicePath is not None:
1009                         tmp=self.servicePath[:]
1010                         tmp.append(ref)
1011                         try:
1012                                 del self.history[self.history_pos+1:]
1013                         except:
1014                                 pass
1015                         self.history.append(tmp)
1016                         hlen = len(self.history)
1017                         if hlen > HISTORYSIZE:
1018                                 del self.history[0]
1019                                 hlen -= 1
1020                         self.history_pos = hlen-1
1021
1022         def historyBack(self):
1023                 hlen = len(self.history)
1024                 if hlen > 1 and self.history_pos > 0:
1025                         self.history_pos -= 1
1026                         self.setHistoryPath()
1027
1028         def historyNext(self):
1029                 hlen = len(self.history)
1030                 if hlen > 1 and self.history_pos < (hlen-1):
1031                         self.history_pos += 1
1032                         self.setHistoryPath()
1033
1034         def setHistoryPath(self):
1035                 path = self.history[self.history_pos][:]
1036                 ref = path.pop()
1037                 del self.servicePath[:]
1038                 self.servicePath += path
1039                 self.saveRoot()
1040                 plen = len(path)
1041                 root = path[plen-1]
1042                 if self.getRoot() != root:
1043                         self.setRoot(root)
1044                 self.session.nav.playService(ref)
1045                 self.setCurrentSelection(ref)
1046                 self.saveChannel()
1047
1048         def saveRoot(self):
1049                 path = ''
1050                 for i in self.servicePath:
1051                         path += i.toString()
1052                         path += ';'
1053                 if len(path) and path != self.lastroot.value:
1054                         self.lastroot.value = path
1055                         self.lastroot.save()
1056
1057         def restoreRoot(self):
1058                 self.clearPath()
1059                 re = compile('.+?;')
1060                 tmp = re.findall(self.lastroot.value)
1061                 cnt = 0
1062                 for i in tmp:
1063                         self.servicePath.append(eServiceReference(i[:len(i)-1]))
1064                         cnt += 1
1065                 if cnt:
1066                         path = self.servicePath.pop()
1067                         self.enterPath(path)
1068                 else:
1069                         self.showFavourites()
1070                         self.saveRoot()
1071
1072         def preEnterPath(self, refstr):
1073                 if len(self.servicePath) and self.servicePath[0] != eServiceReference(refstr):
1074                         pathstr = self.lastroot.value
1075                         if pathstr is not None and pathstr.find(refstr) == 0:
1076                                 self.restoreRoot()
1077                                 lastservice=eServiceReference(self.lastservice.value)
1078                                 if lastservice.valid():
1079                                         self.setCurrentSelection(lastservice)
1080                                 return True
1081                 return False
1082
1083         def saveChannel(self):
1084                 ref = self.session.nav.getCurrentlyPlayingServiceReference()
1085                 if ref is not None:
1086                         refstr = ref.toString()
1087                 else:
1088                         refstr = ""
1089                 if refstr != self.lastservice.value:
1090                         self.lastservice.value = refstr
1091                         self.lastservice.save()
1092
1093         def setCurrentServicePath(self, path):
1094                 hlen = len(self.history)
1095                 if hlen > 0:
1096                         self.history[self.history_pos] = path
1097                 else:
1098                         self.history.append(path)
1099                 self.setHistoryPath()
1100
1101         def getCurrentServicePath(self):
1102                 hlen = len(self.history)
1103                 if hlen > 0:
1104                         return self.history[self.history_pos]
1105                 return None
1106
1107         def recallPrevService(self):
1108                 hlen = len(self.history)
1109                 if hlen > 1:
1110                         if self.history_pos == hlen-1:
1111                                 tmp = self.history[self.history_pos]
1112                                 self.history[self.history_pos] = self.history[self.history_pos-1]
1113                                 self.history[self.history_pos-1] = tmp
1114                         else:
1115                                 tmp = self.history[self.history_pos+1]
1116                                 self.history[self.history_pos+1] = self.history[self.history_pos]
1117                                 self.history[self.history_pos] = tmp
1118                         self.setHistoryPath()
1119
1120         def cancel(self):
1121                 if self.revertMode is None:
1122                         self.restoreRoot()
1123                         lastservice=eServiceReference(self.lastservice.value)
1124                         if lastservice.valid() and self.getCurrentSelection() != lastservice:
1125                                 self.setCurrentSelection(lastservice)
1126                 elif self.revertMode == MODE_TV:
1127                         self.setModeTv()
1128                 elif self.revertMode == MODE_RADIO:
1129                         self.setModeRadio()
1130                 self.revertMode = None
1131                 self.close(None)
1132
1133 from Screens.InfoBarGenerics import InfoBarEvent, InfoBarServiceName, InfoBarInstantRecord, InfoBarRadioText
1134
1135 class RadioInfoBar(Screen, InfoBarEvent, InfoBarServiceName, InfoBarInstantRecord):
1136         def __init__(self, session):
1137                 Screen.__init__(self, session)
1138                 InfoBarEvent.__init__(self)
1139                 InfoBarServiceName.__init__(self)
1140                 InfoBarInstantRecord.__init__(self)
1141                 self["CurrentTime"] = Clock()
1142
1143 class ChannelSelectionRadio(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelectionEPG, InfoBarRadioText):
1144
1145         ALLOW_SUSPEND = True
1146
1147         def __init__(self, session):
1148                 ChannelSelectionBase.__init__(self, session)
1149                 ChannelSelectionEdit.__init__(self)
1150                 ChannelSelectionEPG.__init__(self)
1151                 InfoBarRadioText.__init__(self)
1152
1153                 config.radio = ConfigSubsection();
1154                 config.radio.lastservice = ConfigText()
1155                 config.radio.lastroot = ConfigText()
1156                 self.onLayoutFinish.append(self.onCreate)
1157
1158                 self.info = session.instantiateDialog(RadioInfoBar)
1159
1160                 self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"],
1161                         {
1162                                 "keyTV": self.closeRadio,
1163                                 "keyRadio": self.closeRadio,
1164                                 "cancel": self.closeRadio,
1165                                 "ok": self.channelSelected,
1166                         })
1167
1168         def saveRoot(self):
1169                 path = ''
1170                 for i in self.servicePathRadio:
1171                         path += i.toString()
1172                         path += ';'
1173                 if len(path) and path != config.radio.lastroot.value:
1174                         config.radio.lastroot.value = path
1175                         config.radio.lastroot.save()
1176
1177         def restoreRoot(self):
1178                 self.clearPath()
1179                 re = compile('.+?;')
1180                 tmp = re.findall(config.radio.lastroot.value)
1181                 cnt = 0
1182                 for i in tmp:
1183                         self.servicePathRadio.append(eServiceReference(i[:len(i)-1]))
1184                         cnt += 1
1185                 if cnt:
1186                         path = self.servicePathRadio.pop()
1187                         self.enterPath(path)
1188                 else:
1189                         self.showFavourites()
1190                         self.saveRoot()
1191
1192         def preEnterPath(self, refstr):
1193                 if len(self.servicePathRadio) and self.servicePathRadio[0] != eServiceReference(refstr):
1194                         pathstr = config.radio.lastroot.value
1195                         if pathstr is not None and pathstr.find(refstr) == 0:
1196                                 self.restoreRoot()
1197                                 lastservice=eServiceReference(config.radio.lastservice.value)
1198                                 if lastservice.valid():
1199                                         self.setCurrentSelection(lastservice)
1200                                 return True
1201                 return False
1202
1203         def onCreate(self):
1204                 self.setRadioMode()
1205                 self.restoreRoot()
1206                 lastservice=eServiceReference(config.radio.lastservice.value)
1207                 if lastservice.valid():
1208                         self.servicelist.setCurrent(lastservice)
1209                         self.session.nav.playService(lastservice)
1210                         self.servicelist.setPlayableIgnoreService(lastservice)
1211                 self.info.show()
1212
1213         def channelSelected(self): # just return selected service
1214                 ref = self.getCurrentSelection()
1215                 if self.movemode:
1216                         self.toggleMoveMarked()
1217                 elif (ref.flags & 7) == 7:
1218                         self.enterPath(ref)
1219                 elif self.bouquet_mark_edit:
1220                         self.doMark()
1221                 elif not (ref.flags & 64): # no marker
1222                         playingref = self.session.nav.getCurrentlyPlayingServiceReference()
1223                         if playingref is None or playingref != ref:
1224                                 self.session.nav.playService(ref)
1225                                 self.servicelist.setPlayableIgnoreService(ref)
1226                                 config.radio.lastservice.value = ref.toString()
1227                                 config.radio.lastservice.save()
1228                         self.saveRoot()
1229
1230         def closeRadio(self):
1231                 self.info.hide()
1232                 #set previous tv service
1233                 lastservice=eServiceReference(config.tv.lastservice.value)
1234                 self.session.nav.playService(lastservice)
1235                 self.close(None)
1236
1237 class SimpleChannelSelection(ChannelSelectionBase):
1238         def __init__(self, session, title):
1239                 ChannelSelectionBase.__init__(self, session)
1240                 self.title = title
1241                 self.onShown.append(self.__onExecCallback)
1242
1243                 self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"],
1244                         {
1245                                 "cancel": self.close,
1246                                 "ok": self.channelSelected,
1247                                 "keyRadio": self.setModeRadio,
1248                                 "keyTV": self.setModeTv,
1249                         })
1250
1251         def __onExecCallback(self):
1252                 self.setTitle(self.title)
1253                 self.setModeTv()
1254
1255         def channelSelected(self): # just return selected service
1256                 ref = self.getCurrentSelection()
1257                 if (ref.flags & 7) == 7:
1258                         self.enterPath(ref)
1259                 elif not (ref.flags & 64):
1260                         ref = self.getCurrentSelection()
1261                         self.close(ref)
1262
1263         def setModeTv(self):
1264                 self.setTvMode()
1265                 self.showFavourites()
1266
1267         def setModeRadio(self):
1268                 self.setRadioMode()
1269                 self.showFavourites()