make bouquet +/- keys working in providers and satellites too
[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.pathChangeDisabled = 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.pathChangeDisabled = 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.pathChangeDisabled = 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.pathChangeDisabled:
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.pathChangeDisabled:
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.pathChangeDisabled:
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.pathChangeDisabled:
801                         if len(self.servicePath) > 1:
802                                 #when enter satellite root list we must do some magic stuff..
803                                 ref = eServiceReference('%s FROM SATELLITES ORDER BY satellitePosition'%(self.service_types))
804                                 if self.isBasePathEqual(ref):
805                                         self.showSatellites()
806                                 else:
807                                         self.pathUp()
808                                 if direction < 0:
809                                         self.moveUp()
810                                 else:
811                                         self.moveDown()
812                                 ref = self.getCurrentSelection()
813                                 self.enterPath(ref)
814
815         def inBouquet(self):
816                 return self.isBasePathEqual(self.bouquet_root)
817
818         def atBegin(self):
819                 return self.servicelist.atBegin()
820
821         def atEnd(self):
822                 return self.servicelist.atEnd()
823
824         def nextBouquet(self):
825                 self.changeBouquet(+1)
826
827         def prevBouquet(self):
828                 self.changeBouquet(-1)
829
830         def showFavourites(self):
831                 if not self.pathChangeDisabled:
832                         if not self.preEnterPath(self.bouquet_rootstr):
833                                 if self.isBasePathEqual(self.bouquet_root):
834                                         self.pathUp()
835                                 else:
836                                         currentRoot = self.getRoot()
837                                         if currentRoot is None or currentRoot != self.bouquet_root:
838                                                 self.clearPath()
839                                                 self.enterPath(self.bouquet_root)
840
841         def keyNumberGlobal(self, number):
842                 unichar = self.numericalTextInput.getKey(number)
843                 charstr = unichar.encode("utf-8")
844                 if len(charstr) == 1:
845                         self.servicelist.moveToChar(charstr[0])
846
847         def getRoot(self):
848                 return self.servicelist.getRoot()
849
850         def getCurrentSelection(self):
851                 return self.servicelist.getCurrent()
852
853         def setCurrentSelection(self, service):
854                 servicepath = service.getPath()
855                 pos = servicepath.find(" FROM BOUQUET")
856                 if pos != -1:
857                         if self.mode == MODE_TV:
858                                 servicepath = '(type == 1)' + servicepath[pos:]
859                         else:
860                                 servicepath = '(type == 2)' + servicepath[pos:]
861                         service.setPath(servicepath)
862                 self.servicelist.setCurrent(service)
863
864         def getBouquetList(self):
865                 bouquets = [ ]
866                 serviceHandler = eServiceCenter.getInstance()
867                 if config.usage.multibouquet.value:
868                         list = serviceHandler.list(self.bouquet_root)
869                         if not list is None:
870                                 while True:
871                                         s = list.getNext()
872                                         if not s.valid():
873                                                 break
874                                         if ((s.flags & eServiceReference.flagDirectory) == eServiceReference.flagDirectory):
875                                                 info = serviceHandler.info(s)
876                                                 if not info is None:
877                                                         bouquets.append((info.getName(s), s))
878                                 return bouquets
879                 else:
880                         info = serviceHandler.info(self.bouquet_root)
881                         if not info is None:
882                                 bouquets.append((info.getName(self.bouquet_root), self.bouquet_root))
883                         return bouquets
884                 return None
885
886         def keyNumber0(self, num):
887                 if len(self.servicePath) > 1:
888                         self.keyGoUp()
889                 else:
890                         self.keyNumberGlobal(num)
891
892         def keyGoUp(self):
893                 if len(self.servicePath) > 1:
894                         if self.isBasePathEqual(self.bouquet_root):
895                                 self.showFavourites()
896                         else:
897                                 ref = eServiceReference('%s FROM SATELLITES ORDER BY satellitePosition'%(self.service_types))
898                                 if self.isBasePathEqual(ref):
899                                         self.showSatellites()
900                                 else:
901                                         ref = eServiceReference('%s FROM PROVIDERS ORDER BY name'%(self.service_types))
902                                         if self.isBasePathEqual(ref):
903                                                 self.showProviders()
904                                         else:
905                                                 self.showAllServices()
906
907         def nextMarker(self):
908                 self.servicelist.moveToNextMarker()
909
910         def prevMarker(self):
911                 self.servicelist.moveToPrevMarker()
912
913 HISTORYSIZE = 20
914
915 #config for lastservice
916 config.tv = ConfigSubsection()
917 config.tv.lastservice = ConfigText()
918 config.tv.lastroot = ConfigText()
919 config.radio = ConfigSubsection()
920 config.radio.lastservice = ConfigText()
921 config.radio.lastroot = ConfigText()
922 config.servicelist = ConfigSubsection()
923 config.servicelist.lastmode = ConfigText(default = "tv")
924
925 class ChannelSelection(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelectionEPG):
926         def __init__(self, session):
927                 ChannelSelectionBase.__init__(self,session)
928                 ChannelSelectionEdit.__init__(self)
929                 ChannelSelectionEPG.__init__(self)
930
931                 self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"],
932                         {
933                                 "cancel": self.cancel,
934                                 "ok": self.channelSelected,
935                                 "keyRadio": self.setModeRadio,
936                                 "keyTV": self.setModeTv,
937                         })
938
939                 self.onShown.append(self.__onShown)
940
941                 self.lastChannelRootTimer = eTimer()
942                 self.lastChannelRootTimer.timeout.get().append(self.__onCreate)
943                 self.lastChannelRootTimer.start(100,True)
944
945                 self.history_tv = [ ]
946                 self.history_radio = [ ]
947                 self.history = self.history_tv
948                 self.history_pos = 0
949
950                 self.lastservice = config.tv.lastservice
951                 self.lastroot = config.tv.lastroot
952                 self.revertMode = None
953
954         def setMode(self):
955                 self.restoreRoot()
956                 lastservice=eServiceReference(self.lastservice.value)
957                 if lastservice.valid():
958                         self.setCurrentSelection(lastservice)
959
960         def setModeTv(self):
961                 if self.revertMode is None and config.servicelist.lastmode.value == "radio":
962                         self.revertMode = MODE_RADIO
963                 self.history = self.history_tv
964                 self.lastservice = config.tv.lastservice
965                 self.lastroot = config.tv.lastroot
966                 config.servicelist.lastmode.value = "tv"
967                 self.setTvMode()
968                 self.setMode()
969
970         def setModeRadio(self):
971                 if self.revertMode is None and config.servicelist.lastmode.value == "tv":
972                         self.revertMode = MODE_TV
973                 if config.usage.e1like_radio_mode.value:
974                         self.history = self.history_radio
975                         self.lastservice = config.radio.lastservice
976                         self.lastroot = config.radio.lastroot
977                         config.servicelist.lastmode.value = "radio"
978                         self.setRadioMode()
979                         self.setMode()
980
981         def __onCreate(self):
982                 if config.usage.e1like_radio_mode.value:
983                         if config.servicelist.lastmode.value == "tv":
984                                 self.setModeTv()
985                         else:
986                                 self.setModeRadio()
987                 else:
988                         self.setModeTv()
989                 lastservice=eServiceReference(self.lastservice.value)
990                 if lastservice.valid():
991                         self.zap()
992
993         def __onShown(self):
994                 self.recallBouquetMode()
995                 ref = self.session.nav.getCurrentlyPlayingServiceReference()
996                 if ref is not None and ref.valid() and ref.getPath() == "":
997                         self.servicelist.setPlayableIgnoreService(ref)
998                 else:
999                         self.servicelist.setPlayableIgnoreService(eServiceReference())
1000
1001         def channelSelected(self):
1002                 ref = self.getCurrentSelection()
1003                 if self.movemode:
1004                         self.toggleMoveMarked()
1005                 elif (ref.flags & 7) == 7:
1006                         self.enterPath(ref)
1007                 elif self.bouquet_mark_edit:
1008                         self.doMark()
1009                 elif not (ref.flags & 64): # no marker
1010                         self.zap()
1011                         self.close(ref)
1012
1013         #called from infoBar and channelSelected
1014         def zap(self):
1015                 self.revertMode=None
1016                 ref = self.session.nav.getCurrentlyPlayingServiceReference()
1017                 nref = self.getCurrentSelection()
1018                 if ref is None or ref != nref:
1019                         self.session.nav.playService(nref)
1020                         self.saveRoot()
1021                         self.saveChannel()
1022                         config.servicelist.lastmode.save()
1023                         self.addToHistory(nref)
1024
1025         def addToHistory(self, ref):
1026                 if self.servicePath is not None:
1027                         tmp=self.servicePath[:]
1028                         tmp.append(ref)
1029                         try:
1030                                 del self.history[self.history_pos+1:]
1031                         except:
1032                                 pass
1033                         self.history.append(tmp)
1034                         hlen = len(self.history)
1035                         if hlen > HISTORYSIZE:
1036                                 del self.history[0]
1037                                 hlen -= 1
1038                         self.history_pos = hlen-1
1039
1040         def historyBack(self):
1041                 hlen = len(self.history)
1042                 if hlen > 1 and self.history_pos > 0:
1043                         self.history_pos -= 1
1044                         self.setHistoryPath()
1045
1046         def historyNext(self):
1047                 hlen = len(self.history)
1048                 if hlen > 1 and self.history_pos < (hlen-1):
1049                         self.history_pos += 1
1050                         self.setHistoryPath()
1051
1052         def setHistoryPath(self):
1053                 path = self.history[self.history_pos][:]
1054                 ref = path.pop()
1055                 del self.servicePath[:]
1056                 self.servicePath += path
1057                 self.saveRoot()
1058                 plen = len(path)
1059                 root = path[plen-1]
1060                 if self.getRoot() != root:
1061                         self.setRoot(root)
1062                 self.session.nav.playService(ref)
1063                 self.setCurrentSelection(ref)
1064                 self.saveChannel()
1065
1066         def saveRoot(self):
1067                 path = ''
1068                 for i in self.servicePath:
1069                         path += i.toString()
1070                         path += ';'
1071                 if len(path) and path != self.lastroot.value:
1072                         self.lastroot.value = path
1073                         self.lastroot.save()
1074
1075         def restoreRoot(self):
1076                 self.clearPath()
1077                 re = compile('.+?;')
1078                 tmp = re.findall(self.lastroot.value)
1079                 cnt = 0
1080                 for i in tmp:
1081                         self.servicePath.append(eServiceReference(i[:len(i)-1]))
1082                         cnt += 1
1083                 if cnt:
1084                         path = self.servicePath.pop()
1085                         self.enterPath(path)
1086                 else:
1087                         self.showFavourites()
1088                         self.saveRoot()
1089
1090         def preEnterPath(self, refstr):
1091                 if len(self.servicePath) and self.servicePath[0] != eServiceReference(refstr):
1092                         pathstr = self.lastroot.value
1093                         if pathstr is not None and pathstr.find(refstr) == 0:
1094                                 self.restoreRoot()
1095                                 lastservice=eServiceReference(self.lastservice.value)
1096                                 if lastservice.valid():
1097                                         self.setCurrentSelection(lastservice)
1098                                 return True
1099                 return False
1100
1101         def saveChannel(self):
1102                 ref = self.session.nav.getCurrentlyPlayingServiceReference()
1103                 if ref is not None:
1104                         refstr = ref.toString()
1105                 else:
1106                         refstr = ""
1107                 if refstr != self.lastservice.value:
1108                         self.lastservice.value = refstr
1109                         self.lastservice.save()
1110
1111         def setCurrentServicePath(self, path):
1112                 hlen = len(self.history)
1113                 if hlen > 0:
1114                         self.history[self.history_pos] = path
1115                 else:
1116                         self.history.append(path)
1117                 self.setHistoryPath()
1118
1119         def getCurrentServicePath(self):
1120                 hlen = len(self.history)
1121                 if hlen > 0:
1122                         return self.history[self.history_pos]
1123                 return None
1124
1125         def recallPrevService(self):
1126                 hlen = len(self.history)
1127                 if hlen > 1:
1128                         if self.history_pos == hlen-1:
1129                                 tmp = self.history[self.history_pos]
1130                                 self.history[self.history_pos] = self.history[self.history_pos-1]
1131                                 self.history[self.history_pos-1] = tmp
1132                         else:
1133                                 tmp = self.history[self.history_pos+1]
1134                                 self.history[self.history_pos+1] = self.history[self.history_pos]
1135                                 self.history[self.history_pos] = tmp
1136                         self.setHistoryPath()
1137
1138         def cancel(self):
1139                 if self.revertMode is None:
1140                         self.restoreRoot()
1141                         lastservice=eServiceReference(self.lastservice.value)
1142                         if lastservice.valid() and self.getCurrentSelection() != lastservice:
1143                                 self.setCurrentSelection(lastservice)
1144                 elif self.revertMode == MODE_TV:
1145                         self.setModeTv()
1146                 elif self.revertMode == MODE_RADIO:
1147                         self.setModeRadio()
1148                 self.revertMode = None
1149                 self.close(None)
1150
1151 from Screens.InfoBarGenerics import InfoBarEvent, InfoBarServiceName, InfoBarInstantRecord, InfoBarRadioText
1152
1153 class RadioInfoBar(Screen, InfoBarEvent, InfoBarServiceName, InfoBarInstantRecord):
1154         def __init__(self, session):
1155                 Screen.__init__(self, session)
1156                 InfoBarEvent.__init__(self)
1157                 InfoBarServiceName.__init__(self)
1158                 InfoBarInstantRecord.__init__(self)
1159                 self["CurrentTime"] = Clock()
1160
1161 class ChannelSelectionRadio(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelectionEPG, InfoBarRadioText):
1162
1163         ALLOW_SUSPEND = True
1164
1165         def __init__(self, session):
1166                 ChannelSelectionBase.__init__(self, session)
1167                 ChannelSelectionEdit.__init__(self)
1168                 ChannelSelectionEPG.__init__(self)
1169                 InfoBarRadioText.__init__(self)
1170
1171                 config.radio = ConfigSubsection();
1172                 config.radio.lastservice = ConfigText()
1173                 config.radio.lastroot = ConfigText()
1174                 self.onLayoutFinish.append(self.onCreate)
1175
1176                 self.info = session.instantiateDialog(RadioInfoBar)
1177
1178                 self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"],
1179                         {
1180                                 "keyTV": self.closeRadio,
1181                                 "keyRadio": self.closeRadio,
1182                                 "cancel": self.closeRadio,
1183                                 "ok": self.channelSelected,
1184                         })
1185
1186         def saveRoot(self):
1187                 path = ''
1188                 for i in self.servicePathRadio:
1189                         path += i.toString()
1190                         path += ';'
1191                 if len(path) and path != config.radio.lastroot.value:
1192                         config.radio.lastroot.value = path
1193                         config.radio.lastroot.save()
1194
1195         def restoreRoot(self):
1196                 self.clearPath()
1197                 re = compile('.+?;')
1198                 tmp = re.findall(config.radio.lastroot.value)
1199                 cnt = 0
1200                 for i in tmp:
1201                         self.servicePathRadio.append(eServiceReference(i[:len(i)-1]))
1202                         cnt += 1
1203                 if cnt:
1204                         path = self.servicePathRadio.pop()
1205                         self.enterPath(path)
1206                 else:
1207                         self.showFavourites()
1208                         self.saveRoot()
1209
1210         def preEnterPath(self, refstr):
1211                 if len(self.servicePathRadio) and self.servicePathRadio[0] != eServiceReference(refstr):
1212                         pathstr = config.radio.lastroot.value
1213                         if pathstr is not None and pathstr.find(refstr) == 0:
1214                                 self.restoreRoot()
1215                                 lastservice=eServiceReference(config.radio.lastservice.value)
1216                                 if lastservice.valid():
1217                                         self.setCurrentSelection(lastservice)
1218                                 return True
1219                 return False
1220
1221         def onCreate(self):
1222                 self.setRadioMode()
1223                 self.restoreRoot()
1224                 lastservice=eServiceReference(config.radio.lastservice.value)
1225                 if lastservice.valid():
1226                         self.servicelist.setCurrent(lastservice)
1227                         self.session.nav.playService(lastservice)
1228                         self.servicelist.setPlayableIgnoreService(lastservice)
1229                 self.info.show()
1230
1231         def channelSelected(self): # just return selected service
1232                 ref = self.getCurrentSelection()
1233                 if self.movemode:
1234                         self.toggleMoveMarked()
1235                 elif (ref.flags & 7) == 7:
1236                         self.enterPath(ref)
1237                 elif self.bouquet_mark_edit:
1238                         self.doMark()
1239                 elif not (ref.flags & 64): # no marker
1240                         playingref = self.session.nav.getCurrentlyPlayingServiceReference()
1241                         if playingref is None or playingref != ref:
1242                                 self.session.nav.playService(ref)
1243                                 self.servicelist.setPlayableIgnoreService(ref)
1244                                 config.radio.lastservice.value = ref.toString()
1245                                 config.radio.lastservice.save()
1246                         self.saveRoot()
1247
1248         def closeRadio(self):
1249                 self.info.hide()
1250                 #set previous tv service
1251                 lastservice=eServiceReference(config.tv.lastservice.value)
1252                 self.session.nav.playService(lastservice)
1253                 self.close(None)
1254
1255 class SimpleChannelSelection(ChannelSelectionBase):
1256         def __init__(self, session, title):
1257                 ChannelSelectionBase.__init__(self, session)
1258                 self.title = title
1259                 self.onShown.append(self.__onExecCallback)
1260
1261                 self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"],
1262                         {
1263                                 "cancel": self.close,
1264                                 "ok": self.channelSelected,
1265                                 "keyRadio": self.setModeRadio,
1266                                 "keyTV": self.setModeTv,
1267                         })
1268
1269         def __onExecCallback(self):
1270                 self.setTitle(self.title)
1271                 self.setModeTv()
1272
1273         def channelSelected(self): # just return selected service
1274                 ref = self.getCurrentSelection()
1275                 if (ref.flags & 7) == 7:
1276                         self.enterPath(ref)
1277                 elif not (ref.flags & 64):
1278                         ref = self.getCurrentSelection()
1279                         self.close(ref)
1280
1281         def setModeTv(self):
1282                 self.setTvMode()
1283                 self.showFavourites()
1284
1285         def setModeRadio(self):
1286                 self.setRadioMode()
1287                 self.showFavourites()