1 from Screen import Screen
2 from Components.Button import Button
3 from Components.ServiceList import ServiceList
4 from Components.ActionMap import NumberActionMap, ActionMap, HelpableActionMap
5 from Components.MenuList import MenuList
6 from Components.ServiceEventTracker import ServiceEventTracker
7 from EpgSelection import EPGSelection
8 from enigma import eServiceReference, eEPGCache, eServiceCenter, eTimer, eDVBDB, iPlayableService, iServiceInformation
9 from Components.config import config, ConfigSubsection, ConfigText
10 from Tools.NumericalTextInput import NumericalTextInput
11 from Components.NimManager import nimmanager
12 from Components.Sources.Source import ObsoleteSource
13 from Components.Sources.RdsDecoder import RdsDecoder
14 from Components.Sources.ServiceEvent import ServiceEvent
15 from Components.Input import Input
16 from Components.ParentalControl import parentalControl
17 from Components.Pixmap import Pixmap
18 from Screens.InputBox import InputBox, PinInput
19 from Screens.MessageBox import MessageBox
20 from Screens.ServiceInfo import ServiceInfo
21 from Screens.RdsDisplay import RassInteractive
22 from ServiceReference import ServiceReference
23 from Tools.BoundFunction import boundFunction
24 from re import compile
27 FLAG_SERVICE_NEW_FOUND = 64 #define in lib/dvb/idvb.h as dxNewFound = 64
29 class BouquetSelector(Screen):
30 def __init__(self, session, bouquets, selectedFunc, enableWrapAround=False):
31 Screen.__init__(self, session)
33 self.selectedFunc=selectedFunc
35 self["actions"] = ActionMap(["OkCancelActions"],
37 "ok": self.okbuttonClick,
38 "cancel": self.cancelClick
40 entrys = [ (x[0], x[1]) for x in bouquets ]
41 self["menu"] = MenuList(entrys, enableWrapAround)
44 cur = self["menu"].getCurrent()
47 def okbuttonClick(self):
48 self.selectedFunc(self.getCurrent())
56 def cancelClick(self):
59 # csel.bouquet_mark_edit values
64 def append_when_current_valid(current, menu, args, level = 0):
65 if current and current.valid() and level <= config.usage.setup_level.index:
68 class ChannelContextMenu(Screen):
69 def __init__(self, session, csel):
70 Screen.__init__(self, session)
71 #raise "we need a better summary screen here"
75 self["actions"] = ActionMap(["OkCancelActions"],
77 "ok": self.okbuttonClick,
78 "cancel": self.cancelClick
82 current = csel.getCurrentSelection()
83 current_root = csel.getRoot()
84 current_sel_path = current.getPath()
85 current_sel_flags = current.flags
86 inBouquetRootList = current_root and current_root.getPath().find('FROM BOUQUET "bouquets.') != -1 #FIXME HACK
87 inBouquet = csel.getMutableList() is not None
88 haveBouquets = config.usage.multibouquet.value
90 if not (len(current_sel_path) or current_sel_flags & (eServiceReference.isDirectory|eServiceReference.isMarker)):
91 append_when_current_valid(current, menu, (_("show transponder info"), self.showServiceInformations), level = 2)
92 if csel.bouquet_mark_edit == OFF and not csel.movemode:
93 if not inBouquetRootList:
94 isPlayable = not (current_sel_flags & (eServiceReference.isMarker|eServiceReference.isDirectory))
96 if config.ParentalControl.configured.value:
97 if parentalControl.getProtectionLevel(csel.getCurrentSelection().toCompareString()) == -1:
98 append_when_current_valid(current, menu, (_("add to parental protection"), boundFunction(self.addParentalProtection, csel.getCurrentSelection())), level = 0)
100 append_when_current_valid(current, menu, (_("remove from parental protection"), boundFunction(self.removeParentalProtection, csel.getCurrentSelection())), level = 0)
102 append_when_current_valid(current, menu, (_("add service to bouquet"), self.addServiceToBouquetSelected), level = 0)
104 append_when_current_valid(current, menu, (_("add service to favourites"), self.addServiceToBouquetSelected), level = 0)
107 if not inBouquet and current_sel_path.find("PROVIDERS") == -1:
108 append_when_current_valid(current, menu, (_("copy to bouquets"), self.copyCurrentToBouquetList), level = 0)
109 if current_sel_path.find("flags == %d" %(FLAG_SERVICE_NEW_FOUND)) != -1:
110 append_when_current_valid(current, menu, (_("remove all new found flags"), self.removeAllNewFoundFlags), level = 0)
112 append_when_current_valid(current, menu, (_("remove entry"), self.removeCurrentService), level = 0)
113 if current_root and current_root.getPath().find("flags == %d" %(FLAG_SERVICE_NEW_FOUND)) != -1:
114 append_when_current_valid(current, menu, (_("remove new found flag"), self.removeNewFoundFlag), level = 0)
116 menu.append((_("add bouquet"), self.showBouquetInputBox))
117 append_when_current_valid(current, menu, (_("remove entry"), self.removeBouquet), level = 0)
119 if inBouquet: # current list is editable?
120 if csel.bouquet_mark_edit == OFF:
121 if not csel.movemode:
122 append_when_current_valid(current, menu, (_("enable move mode"), self.toggleMoveMode), level = 1)
123 if not inBouquetRootList and current_root and not (current_root.flags & eServiceReference.isGroup):
124 menu.append((_("add marker"), self.showMarkerInputBox))
126 append_when_current_valid(current, menu, (_("enable bouquet edit"), self.bouquetMarkStart), level = 0)
128 append_when_current_valid(current, menu, (_("enable favourite edit"), self.bouquetMarkStart), level = 0)
129 if current_sel_flags & eServiceReference.isGroup:
130 append_when_current_valid(current, menu, (_("edit alternatives"), self.editAlternativeServices), level = 2)
131 append_when_current_valid(current, menu, (_("show alternatives"), self.showAlternativeServices), level = 2)
132 append_when_current_valid(current, menu, (_("remove all alternatives"), self.removeAlternativeServices), level = 2)
133 elif not current_sel_flags & eServiceReference.isMarker:
134 append_when_current_valid(current, menu, (_("add alternatives"), self.addAlternativeServices), level = 2)
136 append_when_current_valid(current, menu, (_("disable move mode"), self.toggleMoveMode), level = 0)
138 if csel.bouquet_mark_edit == EDIT_BOUQUET:
140 append_when_current_valid(current, menu, (_("end bouquet edit"), self.bouquetMarkEnd), level = 0)
141 append_when_current_valid(current, menu, (_("abort bouquet edit"), self.bouquetMarkAbort), level = 0)
143 append_when_current_valid(current, menu, (_("end favourites edit"), self.bouquetMarkEnd), level = 0)
144 append_when_current_valid(current, menu, (_("abort favourites edit"), self.bouquetMarkAbort), level = 0)
146 append_when_current_valid(current, menu, (_("end alternatives edit"), self.bouquetMarkEnd), level = 0)
147 append_when_current_valid(current, menu, (_("abort alternatives edit"), self.bouquetMarkAbort), level = 0)
149 menu.append((_("back"), self.cancelClick))
150 self["menu"] = MenuList(menu)
152 def okbuttonClick(self):
153 self["menu"].getCurrent()[1]()
155 def cancelClick(self):
158 def showServiceInformations(self):
159 self.session.open( ServiceInfo, self.csel.getCurrentSelection() )
161 def showBouquetInputBox(self):
162 self.session.openWithCallback(self.bouquetInputCallback, InputBox, title=_("Please enter a name for the new bouquet"), text="bouquetname", maxSize=False, visible_width = 56, type=Input.TEXT)
164 def bouquetInputCallback(self, bouquet):
165 if bouquet is not None:
166 self.csel.addBouquet(bouquet, None)
169 def addParentalProtection(self, service):
170 parentalControl.protectService(service.toCompareString())
173 def removeParentalProtection(self, service):
174 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"))
176 def pinEntered(self, service, result):
178 parentalControl.unProtectService(service)
181 self.session.openWithCallback(self.close, MessageBox, _("The pin code you entered is wrong."), MessageBox.TYPE_ERROR)
183 def addServiceToBouquetSelected(self):
184 bouquets = self.csel.getBouquetList()
189 if cnt > 1: # show bouquet list
190 self.bsel = self.session.openWithCallback(self.bouquetSelClosed, BouquetSelector, bouquets, self.addCurrentServiceToBouquet)
191 elif cnt == 1: # add to only one existing bouquet
192 self.addCurrentServiceToBouquet(bouquets[0][1])
194 def bouquetSelClosed(self, recursive):
199 def copyCurrentToBouquetList(self):
200 self.csel.copyCurrentToBouquetList()
203 def removeBouquet(self):
204 self.csel.removeBouquet()
207 def showMarkerInputBox(self):
208 self.session.openWithCallback(self.markerInputCallback, InputBox, title=_("Please enter a name for the new marker"), text="markername", maxSize=False, visible_width = 56, type=Input.TEXT)
210 def markerInputCallback(self, marker):
211 if marker is not None:
212 self.csel.addMarker(marker)
215 def addCurrentServiceToBouquet(self, dest):
216 self.csel.addServiceToBouquet(dest)
217 if self.bsel is not None:
218 self.bsel.close(True)
220 self.close(True) # close bouquet selection
222 def removeCurrentService(self):
223 self.csel.removeCurrentService()
226 def toggleMoveMode(self):
227 self.csel.toggleMoveMode()
230 def bouquetMarkStart(self):
231 self.csel.startMarkedEdit(EDIT_BOUQUET)
234 def bouquetMarkEnd(self):
235 self.csel.endMarkedEdit(abort=False)
238 def bouquetMarkAbort(self):
239 self.csel.endMarkedEdit(abort=True)
242 def removeNewFoundFlag(self):
243 eDVBDB.getInstance().removeFlag(self.csel.getCurrentSelection(), FLAG_SERVICE_NEW_FOUND)
246 def removeAllNewFoundFlags(self):
247 curpath = self.csel.getCurrentSelection().getPath()
248 idx = curpath.find("satellitePosition == ")
250 tmp = curpath[idx+21:]
253 satpos = int(tmp[:idx])
254 eDVBDB.getInstance().removeFlags(FLAG_SERVICE_NEW_FOUND, -1, -1, -1, satpos)
257 def editAlternativeServices(self):
258 self.csel.startMarkedEdit(EDIT_ALTERNATIVES)
261 def showAlternativeServices(self):
262 self.csel.enterPath(self.csel.getCurrentSelection())
265 def removeAlternativeServices(self):
266 self.csel.removeAlternativeServices()
269 def addAlternativeServices(self):
270 self.csel.addAlternativeServices()
271 self.csel.startMarkedEdit(EDIT_ALTERNATIVES)
274 class SelectionEventInfo:
276 self["ServiceEvent"] = ServiceEvent()
277 self.servicelist.connectSelChanged(self.__selectionChanged)
278 self.timer = eTimer()
279 self.timer.timeout.get().append(self.updateEventInfo)
280 self.onShown.append(self.__selectionChanged)
282 def __selectionChanged(self):
284 self.timer.start(100, True)
286 def updateEventInfo(self):
287 cur = self.getCurrentSelection()
288 self["ServiceEvent"].newService(cur)
290 class ChannelSelectionEPG:
292 self["ChannelSelectEPGActions"] = ActionMap(["ChannelSelectEPGActions"],
294 "showEPGList": self.showEPGList,
297 def showEPGList(self):
298 ref=self.getCurrentSelection()
299 ptr=eEPGCache.getInstance()
300 if ptr.startTimeQuery(ref) != -1:
301 self.session.open(EPGSelection, ref)
303 print 'no epg for service', ref.toString()
305 class ChannelSelectionEdit:
307 self.entry_marked = False
308 self.movemode = False
309 self.bouquet_mark_edit = OFF
310 self.mutableList = None
312 self.saved_title = None
313 self.saved_root = None
315 class ChannelSelectionEditActionMap(ActionMap):
316 def __init__(self, csel, contexts = [ ], actions = { }, prio=0):
317 ActionMap.__init__(self, contexts, actions, prio)
320 def action(self, contexts, action):
321 if action == "cancel":
322 self.csel.handleEditCancel()
323 return 0 # fall-trough
325 return 0 # fall-trough
327 return ActionMap.action(self, contexts, action)
329 self["ChannelSelectEditActions"] = ChannelSelectionEditActionMap(self, ["ChannelSelectEditActions", "OkCancelActions"],
331 "contextMenu": self.doContext,
334 def getMutableList(self, root=eServiceReference()):
335 if not self.mutableList is None:
336 return self.mutableList
337 serviceHandler = eServiceCenter.getInstance()
340 list = root and serviceHandler.list(root)
342 return list.startEdit()
345 def buildBouquetID(self, str):
349 if (c >= 'a' and c <= 'z') or (c >= '0' and c <= '9'):
355 def addMarker(self, name):
356 current = self.servicelist.getCurrent()
357 mutableList = self.getMutableList()
360 str = '1:64:%d:0:0:0:0:0:0:0::%s'%(cnt, name)
361 ref = eServiceReference(str)
362 if current and current.valid():
363 if not mutableList.addService(ref, current):
364 self.servicelist.addService(ref, True)
365 mutableList.flushChanges()
367 elif not mutableList.addService(ref):
368 self.servicelist.addService(ref, True)
369 mutableList.flushChanges()
373 def addAlternativeServices(self):
374 cur_service = ServiceReference(self.getCurrentSelection())
375 root = self.getRoot()
376 cur_root = root and ServiceReference(root)
377 mutableBouquet = cur_root.list().startEdit()
379 name = cur_service.getServiceName()
381 if self.mode == MODE_TV:
382 str = '1:134:1:0:0:0:0:0:0:0:FROM BOUQUET \"alternatives.%s.tv\" ORDER BY bouquet'%(self.buildBouquetID(name))
384 str = '1:134:2:0:0:0:0:0:0:0:FROM BOUQUET \"alternatives.%s.radio\" ORDER BY bouquet'%(self.buildBouquetID(name))
385 new_ref = ServiceReference(str)
386 if not mutableBouquet.addService(new_ref.ref, cur_service.ref):
387 mutableBouquet.removeService(cur_service.ref)
388 mutableBouquet.flushChanges()
389 eDVBDB.getInstance().reloadBouquets()
390 mutableAlternatives = new_ref.list().startEdit()
391 if mutableAlternatives:
392 mutableAlternatives.setListName(name)
393 if mutableAlternatives.addService(cur_service.ref):
394 print "add", cur_service.toString(), "to new alternatives failed"
395 mutableAlternatives.flushChanges()
396 self.servicelist.addService(new_ref.ref, True)
397 self.servicelist.removeCurrent()
398 self.servicelist.moveUp()
400 print "get mutable list for new created alternatives failed"
402 print "add", str, "to", cur_root.getServiceName(), "failed"
404 print "bouquetlist is not editable"
406 def addBouquet(self, bName, services):
407 serviceHandler = eServiceCenter.getInstance()
408 mutableBouquetList = serviceHandler.list(self.bouquet_root).startEdit()
409 if mutableBouquetList:
410 if self.mode == MODE_TV:
412 str = '1:7:1:0:0:0:0:0:0:0:(type == 1) FROM BOUQUET \"userbouquet.%s.tv\" ORDER BY bouquet'%(self.buildBouquetID(bName))
415 str = '1:7:2:0:0:0:0:0:0:0:(type == 2) FROM BOUQUET \"userbouquet.%s.radio\" ORDER BY bouquet'%(self.buildBouquetID(bName))
416 new_bouquet_ref = eServiceReference(str)
417 if not mutableBouquetList.addService(new_bouquet_ref):
418 mutableBouquetList.flushChanges()
419 eDVBDB.getInstance().reloadBouquets()
420 mutableBouquet = serviceHandler.list(new_bouquet_ref).startEdit()
422 mutableBouquet.setListName(bName)
423 if services is not None:
424 for service in services:
425 if mutableBouquet.addService(service):
426 print "add", service.toString(), "to new bouquet failed"
427 mutableBouquet.flushChanges()
429 print "get mutable list for new created bouquet failed"
430 # do some voodoo to check if current_root is equal to bouquet_root
431 cur_root = self.getRoot();
432 str1 = cur_root and cur_root.toString()
433 pos1 = str1 and str1.find("FROM BOUQUET") or -1
434 pos2 = self.bouquet_rootstr.find("FROM BOUQUET")
435 if pos1 != -1 and pos2 != -1 and str1[pos1:] == self.bouquet_rootstr[pos2:]:
436 self.servicelist.addService(new_bouquet_ref)
438 print "add", str, "to bouquets failed"
440 print "bouquetlist is not editable"
442 def copyCurrentToBouquetList(self):
443 provider = ServiceReference(self.getCurrentSelection())
444 providerName = provider.getServiceName()
445 serviceHandler = eServiceCenter.getInstance()
446 services = serviceHandler.list(provider.ref)
447 self.addBouquet(providerName, services and services.getContent('R', True))
449 def removeAlternativeServices(self):
450 cur_service = ServiceReference(self.getCurrentSelection())
451 root = self.getRoot()
452 cur_root = root and ServiceReference(root)
453 list = cur_service.list()
454 first_in_alternative = list and list.getNext()
455 if first_in_alternative:
456 edit_root = cur_root and cur_root.list().startEdit()
458 if not edit_root.addService(first_in_alternative, cur_service.ref):
459 self.servicelist.addService(first_in_alternative, True)
461 print "couldn't add first alternative service to current root"
463 print "couldn't edit current root!!"
465 print "remove empty alternative list !!"
467 self.servicelist.moveUp()
469 def removeBouquet(self):
470 refstr = self.getCurrentSelection().toString()
471 print "removeBouquet", refstr
472 self.bouquetNumOffsetCache = { }
473 pos = refstr.find('FROM BOUQUET "')
476 refstr = refstr[pos+14:]
477 pos = refstr.find('"')
479 filename = '/etc/enigma2/' + refstr[:pos] # FIXMEEE !!! HARDCODED /etc/enigma2
480 self.removeCurrentService()
482 if filename is not None:
485 print "error during remove of", filename
487 # multiple marked entry stuff ( edit mode, later multiepg selection )
488 def startMarkedEdit(self, type):
489 self.savedPath = self.servicePath[:]
490 if type == EDIT_ALTERNATIVES:
491 self.enterPath(self.getCurrentSelection())
492 self.mutableList = self.getMutableList()
493 # add all services from the current list to internal marked set in listboxservicecontent
494 self.clearMarks() # this clears the internal marked set in the listboxservicecontent
495 self.saved_title = self.instance.getTitle()
496 pos = self.saved_title.find(')')
497 new_title = self.saved_title[:pos+1]
498 if type == EDIT_ALTERNATIVES:
499 self.bouquet_mark_edit = EDIT_ALTERNATIVES
500 new_title += ' ' + _("[alternative edit]")
502 self.bouquet_mark_edit = EDIT_BOUQUET
503 if config.usage.multibouquet.value:
504 new_title += ' ' + _("[bouquet edit]")
506 new_title += ' ' + _("[favourite edit]")
507 self.setTitle(new_title)
508 self.__marked = self.servicelist.getRootServices()
509 for x in self.__marked:
510 self.servicelist.addMarked(eServiceReference(x))
511 self.showAllServices()
513 def endMarkedEdit(self, abort):
514 if not abort and self.mutableList is not None:
515 self.bouquetNumOffsetCache = { }
516 new_marked = set(self.servicelist.getMarked())
517 old_marked = set(self.__marked)
518 removed = old_marked - new_marked
519 added = new_marked - old_marked
523 self.mutableList.removeService(eServiceReference(x))
526 self.mutableList.addService(eServiceReference(x))
528 self.mutableList.flushChanges()
531 self.bouquet_mark_edit = OFF
532 self.mutableList = None
533 self.setTitle(self.saved_title)
534 self.saved_title = None
535 # self.servicePath is just a reference to servicePathTv or Radio...
536 # so we never ever do use the asignment operator in self.servicePath
537 del self.servicePath[:] # remove all elements
538 self.servicePath += self.savedPath # add saved elements
540 self.setRoot(self.servicePath[len(self.servicePath)-1])
542 def clearMarks(self):
543 self.servicelist.clearMarks()
546 ref = self.servicelist.getCurrent()
547 if self.servicelist.isMarked(ref):
548 self.servicelist.removeMarked(ref)
550 self.servicelist.addMarked(ref)
552 def removeCurrentService(self):
553 ref = self.servicelist.getCurrent()
554 mutableList = self.getMutableList()
555 if ref.valid() and mutableList is not None:
556 if not mutableList.removeService(ref):
557 self.bouquetNumOffsetCache = { }
558 mutableList.flushChanges() #FIXME dont flush on each single removed service
559 self.servicelist.removeCurrent()
561 def addServiceToBouquet(self, dest, service=None):
562 mutableList = self.getMutableList(dest)
563 if not mutableList is None:
564 if service is None: #use current selected service
565 service = self.servicelist.getCurrent()
566 if not mutableList.addService(service):
567 self.bouquetNumOffsetCache = { }
568 mutableList.flushChanges()
569 # do some voodoo to check if current_root is equal to dest
570 cur_root = self.getRoot();
571 str1 = cur_root and cur_root.toString() or -1
572 str2 = dest.toString()
573 pos1 = str1.find("FROM BOUQUET")
574 pos2 = str2.find("FROM BOUQUET")
575 if pos1 != -1 and pos2 != -1 and str1[pos1:] == str2[pos2:]:
576 self.servicelist.addService(service)
578 def toggleMoveMode(self):
580 if self.entry_marked:
581 self.toggleMoveMarked() # unmark current entry
582 self.movemode = False
583 self.pathChangeDisabled = False # re-enable path change
584 self.mutableList.flushChanges() # FIXME add check if changes was made
585 self.mutableList = None
586 self.setTitle(self.saved_title)
587 self.saved_title = None
588 cur_root = self.getRoot()
589 if cur_root and cur_root == self.bouquet_root:
590 self.bouquetNumOffsetCache = { }
592 self.mutableList = self.getMutableList()
594 self.pathChangeDisabled = True # no path change allowed in movemode
595 self.saved_title = self.instance.getTitle()
596 new_title = self.saved_title
597 pos = self.saved_title.find(')')
598 new_title = self.saved_title[:pos+1] + ' ' + _("[move mode]") + self.saved_title[pos+1:]
599 self.setTitle(new_title);
601 def handleEditCancel(self):
602 if self.movemode: #movemode active?
603 self.channelSelected() # unmark
604 self.toggleMoveMode() # disable move mode
605 elif self.bouquet_mark_edit != OFF:
606 self.endMarkedEdit(True) # abort edit mode
608 def toggleMoveMarked(self):
609 if self.entry_marked:
610 self.servicelist.setCurrentMarked(False)
611 self.entry_marked = False
613 self.servicelist.setCurrentMarked(True)
614 self.entry_marked = True
617 self.session.open(ChannelContextMenu, self)
622 # this makes it much simple to implement a selectable radio or tv mode :)
623 service_types_tv = '1:7:1:0:0:0:0:0:0:0:(type == 1) || (type == 17) || (type == 195) || (type == 25)'
624 service_types_radio = '1:7:2:0:0:0:0:0:0:0:(type == 2)'
626 class ChannelSelectionBase(Screen):
627 def __init__(self, session):
628 Screen.__init__(self, session)
630 self["key_red"] = Button(_("All"))
631 self["key_green"] = Button(_("Satellites"))
632 self["key_yellow"] = Button(_("Provider"))
633 self["key_blue"] = Button(_("Favourites"))
635 self["list"] = ServiceList()
636 self.servicelist = self["list"]
638 self.numericalTextInput = NumericalTextInput()
639 self.numericalTextInput.setUseableChars(u'1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ')
641 self.servicePathTV = [ ]
642 self.servicePathRadio = [ ]
643 self.servicePath = [ ]
647 self.pathChangeDisabled = False
649 self.bouquetNumOffsetCache = { }
651 self["ChannelSelectBaseActions"] = NumberActionMap(["ChannelSelectBaseActions", "NumberActions"],
653 "showFavourites": self.showFavourites,
654 "showAllServices": self.showAllServices,
655 "showProviders": self.showProviders,
656 "showSatellites": self.showSatellites,
657 "nextBouquet": self.nextBouquet,
658 "prevBouquet": self.prevBouquet,
659 "nextMarker": self.nextMarker,
660 "prevMarker": self.prevMarker,
661 "1": self.keyNumberGlobal,
662 "2": self.keyNumberGlobal,
663 "3": self.keyNumberGlobal,
664 "4": self.keyNumberGlobal,
665 "5": self.keyNumberGlobal,
666 "6": self.keyNumberGlobal,
667 "7": self.keyNumberGlobal,
668 "8": self.keyNumberGlobal,
669 "9": self.keyNumberGlobal,
672 self.recallBouquetMode()
674 def getBouquetNumOffset(self, bouquet):
675 if not config.usage.multibouquet.value:
677 str = bouquet.toString()
679 if not self.bouquetNumOffsetCache.has_key(str):
680 serviceHandler = eServiceCenter.getInstance()
681 bouquetlist = serviceHandler.list(self.bouquet_root)
682 if not bouquetlist is None:
684 bouquetIterator = bouquetlist.getNext()
685 if not bouquetIterator.valid(): #end of list
687 self.bouquetNumOffsetCache[bouquetIterator.toString()]=offsetCount
688 if not (bouquetIterator.flags & eServiceReference.isDirectory):
690 servicelist = serviceHandler.list(bouquetIterator)
691 if not servicelist is None:
693 serviceIterator = servicelist.getNext()
694 if not serviceIterator.valid(): #check if end of list
696 playable = not (serviceIterator.flags & (eServiceReference.isDirectory|eServiceReference.isMarker))
699 return self.bouquetNumOffsetCache.get(str, offsetCount)
701 def recallBouquetMode(self):
702 if self.mode == MODE_TV:
703 self.service_types = service_types_tv
704 if config.usage.multibouquet.value:
705 self.bouquet_rootstr = '1:7:1:0:0:0:0:0:0:0:FROM BOUQUET "bouquets.tv" ORDER BY bouquet'
707 self.bouquet_rootstr = '%s FROM BOUQUET "userbouquet.favourites.tv" ORDER BY bouquet'%(self.service_types)
709 self.service_types = service_types_radio
710 if config.usage.multibouquet.value:
711 self.bouquet_rootstr = '1:7:1:0:0:0:0:0:0:0:FROM BOUQUET "bouquets.radio" ORDER BY bouquet'
713 self.bouquet_rootstr = '%s FROM BOUQUET "userbouquet.favourites.radio" ORDER BY bouquet'%(self.service_types)
714 self.bouquet_root = eServiceReference(self.bouquet_rootstr)
718 self.servicePath = self.servicePathTV
719 self.recallBouquetMode()
720 title = self.instance.getTitle()
721 pos = title.find(" (")
727 def setRadioMode(self):
728 self.mode = MODE_RADIO
729 self.servicePath = self.servicePathRadio
730 self.recallBouquetMode()
731 title = self.instance.getTitle()
732 pos = title.find(" (")
738 def setRoot(self, root, justSet=False):
739 path = root.getPath()
740 inBouquetRootList = path.find('FROM BOUQUET "bouquets.') != -1 #FIXME HACK
741 pos = path.find('FROM BOUQUET')
742 isBouquet = (pos != -1) and (root.flags & eServiceReference.isDirectory)
743 if not inBouquetRootList and isBouquet:
744 self.servicelist.setMode(ServiceList.MODE_FAVOURITES)
745 self.servicelist.setNumberOffset(self.getBouquetNumOffset(root))
747 self.servicelist.setMode(ServiceList.MODE_NORMAL)
748 self.servicelist.setRoot(root, justSet)
749 self.buildTitleString()
751 def removeModeStr(self, str):
752 if self.mode == MODE_TV:
753 pos = str.find(' (TV)')
755 pos = str.find(' (Radio)')
760 def getServiceName(self, ref):
761 str = self.removeModeStr(ServiceReference(ref).getServiceName())
763 pathstr = ref.getPath()
764 if pathstr.find('FROM PROVIDERS') != -1:
766 if pathstr.find('FROM SATELLITES') != -1:
767 return _("Satellites")
768 if pathstr.find(') ORDER BY name') != -1:
772 def buildTitleString(self):
773 titleStr = self.instance.getTitle()
774 pos = titleStr.find(']')
776 pos = titleStr.find(')')
778 titleStr = titleStr[:pos+1]
779 Len = len(self.servicePath)
781 base_ref = self.servicePath[0]
783 end_ref = self.servicePath[Len-1]
786 nameStr = self.getServiceName(base_ref)
787 titleStr += ' ' + nameStr
788 if end_ref is not None:
793 nameStr = self.getServiceName(end_ref)
795 self.setTitle(titleStr)
798 self.servicelist.moveUp()
801 self.servicelist.moveDown()
804 del self.servicePath[:]
806 def enterPath(self, ref, justSet=False):
807 self.servicePath.append(ref)
808 self.setRoot(ref, justSet)
810 def pathUp(self, justSet=False):
811 prev = self.servicePath.pop()
812 length = len(self.servicePath)
814 current = self.servicePath[length-1]
815 self.setRoot(current, justSet)
817 self.setCurrentSelection(prev)
820 def isBasePathEqual(self, ref):
821 if len(self.servicePath) > 1 and self.servicePath[0] == ref:
825 def isPrevPathEqual(self, ref):
826 length = len(self.servicePath)
827 if length > 1 and self.servicePath[length-2] == ref:
831 def preEnterPath(self, refstr):
834 def showAllServices(self):
835 if not self.pathChangeDisabled:
836 refstr = '%s ORDER BY name'%(self.service_types)
837 if not self.preEnterPath(refstr):
838 ref = eServiceReference(refstr)
839 currentRoot = self.getRoot()
840 if currentRoot is None or currentRoot != ref:
844 def showSatellites(self):
845 if not self.pathChangeDisabled:
846 refstr = '%s FROM SATELLITES ORDER BY satellitePosition'%(self.service_types)
847 if not self.preEnterPath(refstr):
848 ref = eServiceReference(refstr)
852 if self.isBasePathEqual(ref):
853 if self.isPrevPathEqual(ref):
855 prev = self.pathUp(justSet)
857 currentRoot = self.getRoot()
858 if currentRoot is None or currentRoot != ref:
861 self.enterPath(ref, True)
863 serviceHandler = eServiceCenter.getInstance()
864 servicelist = serviceHandler.list(ref)
865 if not servicelist is None:
867 service = servicelist.getNext()
868 if not service.valid(): #check if end of list
870 unsigned_orbpos = service.getUnsignedData(4) >> 16
871 orbpos = service.getData(4) >> 16
874 if service.getPath().find("FROM PROVIDER") != -1:
875 service_type = _("Providers")
876 elif service.getPath().find("flags == %d" %(FLAG_SERVICE_NEW_FOUND)) != -1:
877 service_type = _("New")
879 service_type = _("Services")
881 # why we need this cast?
882 service_name = str(nimmanager.getSatDescription(orbpos))
884 if unsigned_orbpos == 0xFFFF: #Cable
885 service_name = _("Cable")
886 elif unsigned_orbpos == 0xEEEE: #Terrestrial
887 service_name = _("Terrestrial")
889 if orbpos > 1800: # west
890 orbpos = 3600 - orbpos
894 service_name = ("%d.%d" + h) % (orbpos / 10, orbpos % 10)
895 service.setName("%s - %s" % (service_name, service_type))
896 self.servicelist.addService(service)
897 cur_ref = self.session.nav.getCurrentlyPlayingServiceReference()
899 pos = self.service_types.rfind(':')
900 refstr = '%s (channelID == %08x%04x%04x) && %s ORDER BY name' %(self.service_types[:pos+1],
901 cur_ref.getUnsignedData(4), # NAMESPACE
902 cur_ref.getUnsignedData(2), # TSID
903 cur_ref.getUnsignedData(3), # ONID
904 self.service_types[pos+1:])
905 ref = eServiceReference(refstr)
906 ref.setName(_("Current Transponder"))
907 self.servicelist.addService(ref)
908 self.servicelist.finishFill()
910 self.setCurrentSelection(prev)
912 def showProviders(self):
913 if not self.pathChangeDisabled:
914 refstr = '%s FROM PROVIDERS ORDER BY name'%(self.service_types)
915 if not self.preEnterPath(refstr):
916 ref = eServiceReference(refstr)
917 if self.isBasePathEqual(ref):
920 currentRoot = self.getRoot()
921 if currentRoot is None or currentRoot != ref:
925 def changeBouquet(self, direction):
926 if not self.pathChangeDisabled:
927 if len(self.servicePath) > 1:
928 #when enter satellite root list we must do some magic stuff..
929 ref = eServiceReference('%s FROM SATELLITES ORDER BY satellitePosition'%(self.service_types))
930 if self.isBasePathEqual(ref):
931 self.showSatellites()
938 ref = self.getCurrentSelection()
942 if len(self.servicePath) > 0 and self.servicePath[0] == self.bouquet_root:
947 return self.servicelist.atBegin()
950 return self.servicelist.atEnd()
952 def nextBouquet(self):
953 self.changeBouquet(+1)
955 def prevBouquet(self):
956 self.changeBouquet(-1)
958 def showFavourites(self):
959 if not self.pathChangeDisabled:
960 if not self.preEnterPath(self.bouquet_rootstr):
961 if self.isBasePathEqual(self.bouquet_root):
964 currentRoot = self.getRoot()
965 if currentRoot is None or currentRoot != self.bouquet_root:
967 self.enterPath(self.bouquet_root)
969 def keyNumberGlobal(self, number):
970 unichar = self.numericalTextInput.getKey(number)
971 charstr = unichar.encode("utf-8")
972 if len(charstr) == 1:
973 self.servicelist.moveToChar(charstr[0])
976 return self.servicelist.getRoot()
978 def getCurrentSelection(self):
979 return self.servicelist.getCurrent()
981 def setCurrentSelection(self, service):
982 servicepath = service.getPath()
983 pos = servicepath.find(" FROM BOUQUET")
985 if self.mode == MODE_TV:
986 servicepath = '(type == 1)' + servicepath[pos:]
988 servicepath = '(type == 2)' + servicepath[pos:]
989 service.setPath(servicepath)
990 self.servicelist.setCurrent(service)
992 def getBouquetList(self):
994 serviceHandler = eServiceCenter.getInstance()
995 if config.usage.multibouquet.value:
996 list = serviceHandler.list(self.bouquet_root)
1002 if s.flags & eServiceReference.isDirectory:
1003 info = serviceHandler.info(s)
1005 bouquets.append((info.getName(s), s))
1008 info = serviceHandler.info(self.bouquet_root)
1010 bouquets.append((info.getName(self.bouquet_root), self.bouquet_root))
1014 def keyNumber0(self, num):
1015 if len(self.servicePath) > 1:
1018 self.keyNumberGlobal(num)
1021 if len(self.servicePath) > 1:
1022 if self.isBasePathEqual(self.bouquet_root):
1023 self.showFavourites()
1025 ref = eServiceReference('%s FROM SATELLITES ORDER BY satellitePosition'%(self.service_types))
1026 if self.isBasePathEqual(ref):
1027 self.showSatellites()
1029 ref = eServiceReference('%s FROM PROVIDERS ORDER BY name'%(self.service_types))
1030 if self.isBasePathEqual(ref):
1031 self.showProviders()
1033 self.showAllServices()
1035 def nextMarker(self):
1036 self.servicelist.moveToNextMarker()
1038 def prevMarker(self):
1039 self.servicelist.moveToPrevMarker()
1043 #config for lastservice
1044 config.tv = ConfigSubsection()
1045 config.tv.lastservice = ConfigText()
1046 config.tv.lastroot = ConfigText()
1047 config.radio = ConfigSubsection()
1048 config.radio.lastservice = ConfigText()
1049 config.radio.lastroot = ConfigText()
1050 config.servicelist = ConfigSubsection()
1051 config.servicelist.lastmode = ConfigText(default = "tv")
1053 class ChannelSelection(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelectionEPG, SelectionEventInfo):
1054 def __init__(self, session):
1055 ChannelSelectionBase.__init__(self,session)
1056 ChannelSelectionEdit.__init__(self)
1057 ChannelSelectionEPG.__init__(self)
1058 SelectionEventInfo.__init__(self)
1060 self["CurrentTime"] = ObsoleteSource(new_source = "global.CurrentTime", removal_date = "2008-01")
1062 self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"],
1064 "cancel": self.cancel,
1065 "ok": self.channelSelected,
1066 "keyRadio": self.setModeRadio,
1067 "keyTV": self.setModeTv,
1070 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
1072 iPlayableService.evStart: self.__evServiceStart,
1073 iPlayableService.evEnd: self.__evServiceEnd
1076 self.lastChannelRootTimer = eTimer()
1077 self.lastChannelRootTimer.timeout.get().append(self.__onCreate)
1078 self.lastChannelRootTimer.start(100,True)
1080 self.history_tv = [ ]
1081 self.history_radio = [ ]
1082 self.history = self.history_tv
1083 self.history_pos = 0
1085 self.lastservice = config.tv.lastservice
1086 self.lastroot = config.tv.lastroot
1087 self.revertMode = None
1088 config.usage.multibouquet.addNotifier(self.multibouquet_config_changed)
1089 self.new_service_played = False
1091 def multibouquet_config_changed(self, val):
1092 self.recallBouquetMode()
1094 def __evServiceStart(self):
1095 service = self.session.nav.getCurrentService()
1097 info = service.info()
1099 refstr = info.getInfoString(iServiceInformation.sServiceref)
1100 self.servicelist.setPlayableIgnoreService(eServiceReference(refstr))
1102 def __evServiceEnd(self):
1103 self.servicelist.setPlayableIgnoreService(eServiceReference())
1107 lastservice=eServiceReference(self.lastservice.value)
1108 if lastservice.valid():
1109 self.setCurrentSelection(lastservice)
1111 def setModeTv(self):
1112 if self.revertMode is None and config.servicelist.lastmode.value == "radio":
1113 self.revertMode = MODE_RADIO
1114 self.history = self.history_tv
1115 self.lastservice = config.tv.lastservice
1116 self.lastroot = config.tv.lastroot
1117 config.servicelist.lastmode.value = "tv"
1121 def setModeRadio(self):
1122 if self.revertMode is None and config.servicelist.lastmode.value == "tv":
1123 self.revertMode = MODE_TV
1124 if config.usage.e1like_radio_mode.value:
1125 self.history = self.history_radio
1126 self.lastservice = config.radio.lastservice
1127 self.lastroot = config.radio.lastroot
1128 config.servicelist.lastmode.value = "radio"
1132 def __onCreate(self):
1133 if config.usage.e1like_radio_mode.value:
1134 if config.servicelist.lastmode.value == "tv":
1140 lastservice=eServiceReference(self.lastservice.value)
1141 if lastservice.valid():
1144 def channelSelected(self):
1145 ref = self.getCurrentSelection()
1147 self.toggleMoveMarked()
1148 elif (ref.flags & 7) == 7:
1150 elif self.bouquet_mark_edit != OFF:
1151 if not (self.bouquet_mark_edit == EDIT_ALTERNATIVES and ref.flags & eServiceReference.isGroup):
1153 elif not (ref.flags & eServiceReference.isMarker): # no marker
1154 root = self.getRoot()
1155 if not root or not (root.flags & eServiceReference.isGroup):
1159 #called from infoBar and channelSelected
1161 self.revertMode=None
1162 ref = self.session.nav.getCurrentlyPlayingServiceReference()
1163 nref = self.getCurrentSelection()
1164 if ref is None or ref != nref:
1165 self.new_service_played = True
1166 self.session.nav.playService(nref)
1168 self.saveChannel(nref)
1169 config.servicelist.lastmode.save()
1170 self.addToHistory(nref)
1172 def newServicePlayed(self):
1173 ret = self.new_service_played
1174 self.new_service_played = False
1177 def addToHistory(self, ref):
1178 if self.servicePath is not None:
1179 tmp=self.servicePath[:]
1182 del self.history[self.history_pos+1:]
1185 self.history.append(tmp)
1186 hlen = len(self.history)
1187 if hlen > HISTORYSIZE:
1190 self.history_pos = hlen-1
1192 def historyBack(self):
1193 hlen = len(self.history)
1194 if hlen > 1 and self.history_pos > 0:
1195 self.history_pos -= 1
1196 self.setHistoryPath()
1198 def historyNext(self):
1199 hlen = len(self.history)
1200 if hlen > 1 and self.history_pos < (hlen-1):
1201 self.history_pos += 1
1202 self.setHistoryPath()
1204 def setHistoryPath(self):
1205 path = self.history[self.history_pos][:]
1207 del self.servicePath[:]
1208 self.servicePath += path
1212 cur_root = self.getRoot()
1213 if cur_root and cur_root != root:
1215 self.session.nav.playService(ref)
1216 self.setCurrentSelection(ref)
1217 self.saveChannel(ref)
1221 for i in self.servicePath:
1222 path += i.toString()
1224 if len(path) and path != self.lastroot.value:
1225 self.lastroot.value = path
1226 self.lastroot.save()
1228 def restoreRoot(self):
1230 re = compile('.+?;')
1231 tmp = re.findall(self.lastroot.value)
1234 self.servicePath.append(eServiceReference(i[:len(i)-1]))
1237 path = self.servicePath.pop()
1238 self.enterPath(path)
1240 self.showFavourites()
1243 def preEnterPath(self, refstr):
1244 if len(self.servicePath) and self.servicePath[0] != eServiceReference(refstr):
1245 pathstr = self.lastroot.value
1246 if pathstr is not None and pathstr.find(refstr) == 0:
1248 lastservice=eServiceReference(self.lastservice.value)
1249 if lastservice.valid():
1250 self.setCurrentSelection(lastservice)
1254 def saveChannel(self, ref):
1256 refstr = ref.toString()
1259 if refstr != self.lastservice.value:
1260 self.lastservice.value = refstr
1261 self.lastservice.save()
1263 def setCurrentServicePath(self, path):
1264 hlen = len(self.history)
1266 self.history[self.history_pos] = path
1268 self.history.append(path)
1269 self.setHistoryPath()
1271 def getCurrentServicePath(self):
1272 hlen = len(self.history)
1274 return self.history[self.history_pos]
1277 def recallPrevService(self):
1278 hlen = len(self.history)
1280 if self.history_pos == hlen-1:
1281 tmp = self.history[self.history_pos]
1282 self.history[self.history_pos] = self.history[self.history_pos-1]
1283 self.history[self.history_pos-1] = tmp
1285 tmp = self.history[self.history_pos+1]
1286 self.history[self.history_pos+1] = self.history[self.history_pos]
1287 self.history[self.history_pos] = tmp
1288 self.setHistoryPath()
1291 if self.revertMode is None:
1293 lastservice=eServiceReference(self.lastservice.value)
1294 if lastservice.valid() and self.getCurrentSelection() != lastservice:
1295 self.setCurrentSelection(lastservice)
1296 elif self.revertMode == MODE_TV:
1298 elif self.revertMode == MODE_RADIO:
1300 self.revertMode = None
1303 from Screens.InfoBarGenerics import InfoBarEvent, InfoBarServiceName
1305 class RadioInfoBar(Screen, InfoBarEvent, InfoBarServiceName):
1306 def __init__(self, session):
1307 Screen.__init__(self, session)
1308 InfoBarEvent.__init__(self)
1309 InfoBarServiceName.__init__(self)
1310 self["CurrentTime"] = ObsoleteSource(new_source = "global.CurrentTime", removal_date = "2008-01")
1311 self["RdsDecoder"] = RdsDecoder(self.session.nav)
1312 self["BlinkingPoint"] = Pixmap()
1313 self["BlinkingPoint"].hide()
1315 class ChannelSelectionRadio(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelectionEPG):
1316 ALLOW_SUSPEND = True
1318 def __init__(self, session, infobar):
1319 ChannelSelectionBase.__init__(self, session)
1320 ChannelSelectionEdit.__init__(self)
1321 ChannelSelectionEPG.__init__(self)
1322 self.infobar = infobar
1323 self.onLayoutFinish.append(self.onCreate)
1325 self.info = session.instantiateDialog(RadioInfoBar) # our simple infobar
1327 self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"],
1329 "keyTV": self.closeRadio,
1330 "keyRadio": self.closeRadio,
1331 "cancel": self.closeRadio,
1332 "ok": self.channelSelected,
1335 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
1337 iPlayableService.evStart: self.__evServiceStart,
1338 iPlayableService.evEnd: self.__evServiceEnd
1341 ########## RDS Radiotext / Rass Support BEGIN
1342 self.infobar = infobar # reference to real infobar (the one and only)
1343 self["RdsDecoder"] = self.info["RdsDecoder"]
1344 self["RdsActions"] = HelpableActionMap(self, "InfobarRdsActions",
1346 "startRassInteractive": (self.startRassInteractive, _("View Rass interactive..."))
1348 self["RdsActions"].setEnabled(False)
1349 infobar.rds_display.onRassInteractivePossibilityChanged.append(self.RassInteractivePossibilityChanged)
1351 def startRassInteractive(self):
1353 self.infobar.rass_interactive = self.session.openWithCallback(self.RassInteractiveClosed, RassInteractive)
1355 def RassInteractiveClosed(self):
1357 self.infobar.rass_interactive = None
1358 self.infobar.RassSlidePicChanged()
1360 def RassInteractivePossibilityChanged(self, state):
1361 self["RdsActions"].setEnabled(state)
1362 ########## RDS Radiotext / Rass Support END
1364 def closeRadio(self):
1365 self.infobar.rds_display.onRassInteractivePossibilityChanged.remove(self.RassInteractivePossibilityChanged)
1367 #set previous tv service
1368 lastservice=eServiceReference(config.tv.lastservice.value)
1369 self.session.nav.playService(lastservice)
1372 def __evServiceStart(self):
1373 service = self.session.nav.getCurrentService()
1375 info = service.info()
1377 refstr = info.getInfoString(iServiceInformation.sServiceref)
1378 self.servicelist.setPlayableIgnoreService(eServiceReference(refstr))
1380 def __evServiceEnd(self):
1381 self.servicelist.setPlayableIgnoreService(eServiceReference())
1385 for i in self.servicePathRadio:
1386 path += i.toString()
1388 if len(path) and path != config.radio.lastroot.value:
1389 config.radio.lastroot.value = path
1390 config.radio.lastroot.save()
1392 def restoreRoot(self):
1394 re = compile('.+?;')
1395 tmp = re.findall(config.radio.lastroot.value)
1398 self.servicePathRadio.append(eServiceReference(i[:len(i)-1]))
1401 path = self.servicePathRadio.pop()
1402 self.enterPath(path)
1404 self.showFavourites()
1407 def preEnterPath(self, refstr):
1408 if len(self.servicePathRadio) and self.servicePathRadio[0] != eServiceReference(refstr):
1409 pathstr = config.radio.lastroot.value
1410 if pathstr is not None and pathstr.find(refstr) == 0:
1412 lastservice=eServiceReference(config.radio.lastservice.value)
1413 if lastservice.valid():
1414 self.setCurrentSelection(lastservice)
1421 lastservice=eServiceReference(config.radio.lastservice.value)
1422 if lastservice.valid():
1423 self.servicelist.setCurrent(lastservice)
1424 self.session.nav.playService(lastservice)
1426 self.session.nav.stopService()
1429 def channelSelected(self): # just return selected service
1430 ref = self.getCurrentSelection()
1432 self.toggleMoveMarked()
1433 elif (ref.flags & 7) == 7:
1435 elif self.bouquet_mark_edit != OFF:
1436 if not (self.bouquet_mark_edit == EDIT_ALTERNATIVES and ref.flags & eServiceReference.isGroup):
1438 elif not (ref.flags & eServiceReference.isMarker): # no marker
1439 cur_root = self.getRoot()
1440 if not cur_root or not (cur_root.flags & eServiceReference.isGroup):
1441 playingref = self.session.nav.getCurrentlyPlayingServiceReference()
1442 if playingref is None or playingref != ref:
1443 self.session.nav.playService(ref)
1444 config.radio.lastservice.value = ref.toString()
1445 config.radio.lastservice.save()
1448 class SimpleChannelSelection(ChannelSelectionBase):
1449 def __init__(self, session, title):
1450 ChannelSelectionBase.__init__(self, session)
1452 self.onShown.append(self.__onExecCallback)
1454 self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"],
1456 "cancel": self.close,
1457 "ok": self.channelSelected,
1458 "keyRadio": self.setModeRadio,
1459 "keyTV": self.setModeTv,
1462 def __onExecCallback(self):
1463 self.setTitle(self.title)
1466 def channelSelected(self): # just return selected service
1467 ref = self.getCurrentSelection()
1468 if (ref.flags & 7) == 7:
1470 elif not (ref.flags & eServiceReference.isMarker):
1471 ref = self.getCurrentSelection()
1474 def setModeTv(self):
1476 self.showFavourites()
1478 def setModeRadio(self):
1480 self.showFavourites()