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