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