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