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