1 from Tools.Profile import profile
3 from Screen import Screen
4 from Components.Button import Button
5 from Components.ServiceList import ServiceList
6 from Components.ActionMap import NumberActionMap, ActionMap, HelpableActionMap
7 from Components.MenuList import MenuList
8 from Components.ServiceEventTracker import ServiceEventTracker, InfoBarBase
9 profile("ChannelSelection.py 1")
10 from EpgSelection import EPGSelection
11 from enigma import eServiceReference, eEPGCache, eServiceCenter, eRCInput, eTimer, eDVBDB, iPlayableService, iServiceInformation, getPrevAsciiCode, eEnv
12 from Components.config import config, ConfigSubsection, ConfigText
13 from Tools.NumericalTextInput import NumericalTextInput
14 profile("ChannelSelection.py 2")
15 from Components.NimManager import nimmanager
16 profile("ChannelSelection.py 2.1")
17 from Components.Sources.RdsDecoder import RdsDecoder
18 profile("ChannelSelection.py 2.2")
19 from Components.Sources.ServiceEvent import ServiceEvent
20 profile("ChannelSelection.py 2.3")
21 from Components.Input import Input
22 profile("ChannelSelection.py 3")
23 from Components.ChoiceList import ChoiceList, ChoiceEntryComponent
24 from Components.SystemInfo import SystemInfo
25 from Screens.InputBox import InputBox, PinInput
26 from Screens.MessageBox import MessageBox
27 from Screens.ServiceInfo import ServiceInfo
28 profile("ChannelSelection.py 4")
29 from Screens.PictureInPicture import PictureInPicture
30 from Screens.RdsDisplay import RassInteractive
31 from ServiceReference import ServiceReference
32 from Tools.BoundFunction import boundFunction
34 profile("ChannelSelection.py after imports")
36 FLAG_SERVICE_NEW_FOUND = 64 #define in lib/dvb/idvb.h as dxNewFound = 64
38 class BouquetSelector(Screen):
39 def __init__(self, session, bouquets, selectedFunc, enableWrapAround=False):
40 Screen.__init__(self, session)
42 self.selectedFunc=selectedFunc
44 self["actions"] = ActionMap(["OkCancelActions"],
46 "ok": self.okbuttonClick,
47 "cancel": self.cancelClick
49 entrys = [ (x[0], x[1]) for x in bouquets ]
50 self["menu"] = MenuList(entrys, enableWrapAround)
53 cur = self["menu"].getCurrent()
56 def okbuttonClick(self):
57 self.selectedFunc(self.getCurrent())
65 def cancelClick(self):
68 class SilentBouquetSelector:
69 def __init__(self, bouquets, enableWrapAround=False, current=0):
70 self.bouquets = [b[1] for b in bouquets]
72 self.count = len(bouquets)
73 self.enableWrapAround = enableWrapAround
76 if self.pos > 0 or self.enableWrapAround:
77 self.pos = (self.pos - 1) % self.count
80 if self.pos < (self.count - 1) or self.enableWrapAround:
81 self.pos = (self.pos + 1) % self.count
84 return self.bouquets[self.pos]
86 # csel.bouquet_mark_edit values
91 def append_when_current_valid(current, menu, args, level = 0, key = ""):
92 if current and current.valid() and level <= config.usage.setup_level.index:
93 menu.append(ChoiceEntryComponent(key, args))
95 class ChannelContextMenu(Screen):
96 def __init__(self, session, csel):
98 Screen.__init__(self, session)
99 #raise Exception("we need a better summary screen here")
103 self["actions"] = ActionMap(["OkCancelActions", "ColorActions", "NumberActions"],
105 "ok": self.okbuttonClick,
106 "cancel": self.cancelClick,
107 "blue": self.showServiceInPiP
111 self.pipAvailable = False
112 current = csel.getCurrentSelection()
113 current_root = csel.getRoot()
114 current_sel_path = current.getPath()
115 current_sel_flags = current.flags
116 inBouquetRootList = current_root and current_root.getPath().find('FROM BOUQUET "bouquets.') != -1 #FIXME HACK
117 inBouquet = csel.getMutableList() is not None
118 haveBouquets = config.usage.multibouquet.value
120 if not (current_sel_path or current_sel_flags & (eServiceReference.isDirectory|eServiceReference.isMarker)):
121 append_when_current_valid(current, menu, (_("show transponder info"), self.showServiceInformations), level = 2)
122 if csel.bouquet_mark_edit == OFF and not csel.movemode:
123 if not inBouquetRootList:
124 isPlayable = not (current_sel_flags & (eServiceReference.isMarker|eServiceReference.isDirectory))
126 if config.ParentalControl.configured.value:
127 from Components.ParentalControl import parentalControl
128 if parentalControl.getProtectionLevel(csel.getCurrentSelection().toCompareString()) == -1:
129 append_when_current_valid(current, menu, (_("add to parental protection"), boundFunction(self.addParentalProtection, csel.getCurrentSelection())), level = 0)
131 append_when_current_valid(current, menu, (_("remove from parental protection"), boundFunction(self.removeParentalProtection, csel.getCurrentSelection())), level = 0)
133 bouquets = self.csel.getBouquetList()
137 bouquetCnt = len(bouquets)
138 if not inBouquet or bouquetCnt > 1:
139 append_when_current_valid(current, menu, (_("add service to bouquet"), self.addServiceToBouquetSelected), level = 0)
142 append_when_current_valid(current, menu, (_("add service to favourites"), self.addServiceToBouquetSelected), level = 0)
144 if 'FROM SATELLITES' in current_root.getPath() and _("Services") in eServiceCenter.getInstance().info(current).getName(current):
145 unsigned_orbpos = current.getUnsignedData(4) >> 16
146 if unsigned_orbpos == 0xFFFF: #Cable
147 append_when_current_valid(current, menu, (_("remove cable services"), self.removeSatelliteServices), level = 0)
148 elif unsigned_orbpos == 0xEEEE: #Terrestrial
149 append_when_current_valid(current, menu, (_("remove terrestrial services"), self.removeSatelliteServices), level = 0)
151 append_when_current_valid(current, menu, (_("remove selected satellite"), self.removeSatelliteServices), level = 0)
153 if not inBouquet and current_sel_path.find("PROVIDERS") == -1:
154 append_when_current_valid(current, menu, (_("copy to bouquets"), self.copyCurrentToBouquetList), level = 0)
155 if current_sel_path.find("flags == %d" %(FLAG_SERVICE_NEW_FOUND)) != -1:
156 append_when_current_valid(current, menu, (_("remove all new found flags"), self.removeAllNewFoundFlags), level = 0)
158 append_when_current_valid(current, menu, (_("remove entry"), self.removeCurrentService), level = 0)
159 if current_root and current_root.getPath().find("flags == %d" %(FLAG_SERVICE_NEW_FOUND)) != -1:
160 append_when_current_valid(current, menu, (_("remove new found flag"), self.removeNewFoundFlag), level = 0)
161 if isPlayable and SystemInfo.get("NumVideoDecoders", 1) > 1:
162 append_when_current_valid(current, menu, (_("Activate Picture in Picture"), self.showServiceInPiP), level = 0, key = "blue")
163 self.pipAvailable = True
165 menu.append(ChoiceEntryComponent(text = (_("add bouquet"), self.showBouquetInputBox)))
166 append_when_current_valid(current, menu, (_("remove entry"), self.removeBouquet), level = 0)
168 if inBouquet: # current list is editable?
169 if csel.bouquet_mark_edit == OFF:
170 if not csel.movemode:
171 append_when_current_valid(current, menu, (_("enable move mode"), self.toggleMoveMode), level = 1)
172 if not inBouquetRootList and current_root and not (current_root.flags & eServiceReference.isGroup):
173 menu.append(ChoiceEntryComponent(text = (_("add marker"), self.showMarkerInputBox)))
175 append_when_current_valid(current, menu, (_("enable bouquet edit"), self.bouquetMarkStart), level = 0)
177 append_when_current_valid(current, menu, (_("enable favourite edit"), self.bouquetMarkStart), level = 0)
178 if current_sel_flags & eServiceReference.isGroup:
179 append_when_current_valid(current, menu, (_("edit alternatives"), self.editAlternativeServices), level = 2)
180 append_when_current_valid(current, menu, (_("show alternatives"), self.showAlternativeServices), level = 2)
181 append_when_current_valid(current, menu, (_("remove all alternatives"), self.removeAlternativeServices), level = 2)
182 elif not current_sel_flags & eServiceReference.isMarker:
183 append_when_current_valid(current, menu, (_("add alternatives"), self.addAlternativeServices), level = 2)
185 append_when_current_valid(current, menu, (_("disable move mode"), self.toggleMoveMode), level = 0)
187 if csel.bouquet_mark_edit == EDIT_BOUQUET:
189 append_when_current_valid(current, menu, (_("end bouquet edit"), self.bouquetMarkEnd), level = 0)
190 append_when_current_valid(current, menu, (_("abort bouquet edit"), self.bouquetMarkAbort), level = 0)
192 append_when_current_valid(current, menu, (_("end favourites edit"), self.bouquetMarkEnd), level = 0)
193 append_when_current_valid(current, menu, (_("abort favourites edit"), self.bouquetMarkAbort), level = 0)
195 append_when_current_valid(current, menu, (_("end alternatives edit"), self.bouquetMarkEnd), level = 0)
196 append_when_current_valid(current, menu, (_("abort alternatives edit"), self.bouquetMarkAbort), level = 0)
198 menu.append(ChoiceEntryComponent(text = (_("back"), self.cancelClick)))
199 self["menu"] = ChoiceList(menu)
201 def okbuttonClick(self):
202 self["menu"].getCurrent()[0][1]()
204 def cancelClick(self):
207 def showServiceInformations(self):
208 self.session.open( ServiceInfo, self.csel.getCurrentSelection() )
210 def showBouquetInputBox(self):
211 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)
213 def bouquetInputCallback(self, bouquet):
214 if bouquet is not None:
215 self.csel.addBouquet(bouquet, None)
218 def addParentalProtection(self, service):
219 from Components.ParentalControl import parentalControl
220 parentalControl.protectService(service.toCompareString())
223 def removeParentalProtection(self, service):
224 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"))
226 def pinEntered(self, service, result):
228 from Components.ParentalControl import parentalControl
229 parentalControl.unProtectService(service)
232 self.session.openWithCallback(self.close, MessageBox, _("The pin code you entered is wrong."), MessageBox.TYPE_ERROR)
234 def showServiceInPiP(self):
235 if not self.pipAvailable:
237 if self.session.pipshown:
239 self.session.pip = self.session.instantiateDialog(PictureInPicture)
240 self.session.pip.setAnimationMode(0)
241 self.session.pip.show()
242 newservice = self.csel.servicelist.getCurrent()
243 if self.session.pip.playService(newservice):
244 self.session.pipshown = True
245 self.session.pip.servicePath = self.csel.getCurrentServicePath()
248 self.session.pipshown = False
250 self.session.openWithCallback(self.close, MessageBox, _("Could not open Picture in Picture"), MessageBox.TYPE_ERROR)
252 def addServiceToBouquetSelected(self):
253 bouquets = self.csel.getBouquetList()
258 if cnt > 1: # show bouquet list
259 self.bsel = self.session.openWithCallback(self.bouquetSelClosed, BouquetSelector, bouquets, self.addCurrentServiceToBouquet)
260 elif cnt == 1: # add to only one existing bouquet
261 self.addCurrentServiceToBouquet(bouquets[0][1], closeBouquetSelection = False)
263 def bouquetSelClosed(self, recursive):
268 def removeSatelliteServices(self):
269 self.csel.removeSatelliteServices()
272 def copyCurrentToBouquetList(self):
273 self.csel.copyCurrentToBouquetList()
276 def removeBouquet(self):
277 self.csel.removeBouquet()
280 def showMarkerInputBox(self):
281 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)
283 def markerInputCallback(self, marker):
284 if marker is not None:
285 self.csel.addMarker(marker)
288 def addCurrentServiceToBouquet(self, dest, closeBouquetSelection = True):
289 self.csel.addServiceToBouquet(dest)
290 if self.bsel is not None:
291 self.bsel.close(True)
293 self.close(closeBouquetSelection) # close bouquet selection
295 def removeCurrentService(self):
296 self.csel.removeCurrentService()
299 def toggleMoveMode(self):
300 self.csel.toggleMoveMode()
303 def bouquetMarkStart(self):
304 self.csel.startMarkedEdit(EDIT_BOUQUET)
307 def bouquetMarkEnd(self):
308 self.csel.endMarkedEdit(abort=False)
311 def bouquetMarkAbort(self):
312 self.csel.endMarkedEdit(abort=True)
315 def removeNewFoundFlag(self):
316 eDVBDB.getInstance().removeFlag(self.csel.getCurrentSelection(), FLAG_SERVICE_NEW_FOUND)
319 def removeAllNewFoundFlags(self):
320 curpath = self.csel.getCurrentSelection().getPath()
321 idx = curpath.find("satellitePosition == ")
323 tmp = curpath[idx+21:]
326 satpos = int(tmp[:idx])
327 eDVBDB.getInstance().removeFlags(FLAG_SERVICE_NEW_FOUND, -1, -1, -1, satpos)
330 def editAlternativeServices(self):
331 self.csel.startMarkedEdit(EDIT_ALTERNATIVES)
334 def showAlternativeServices(self):
335 self.csel.enterPath(self.csel.getCurrentSelection())
338 def removeAlternativeServices(self):
339 self.csel.removeAlternativeServices()
342 def addAlternativeServices(self):
343 self.csel.addAlternativeServices()
344 self.csel.startMarkedEdit(EDIT_ALTERNATIVES)
347 class SelectionEventInfo:
349 self["ServiceEvent"] = ServiceEvent()
350 self.servicelist.connectSelChanged(self.__selectionChanged)
351 self.timer = eTimer()
352 self.timer.callback.append(self.updateEventInfo)
353 self.onShown.append(self.__selectionChanged)
355 def __selectionChanged(self):
357 self.timer.start(100, True)
359 def updateEventInfo(self):
360 cur = self.getCurrentSelection()
361 self["ServiceEvent"].newService(cur)
363 class ChannelSelectionEPG:
365 self["ChannelSelectEPGActions"] = ActionMap(["ChannelSelectEPGActions"],
367 "showEPGList": self.showEPGList,
370 def showEPGList(self):
371 ref=self.getCurrentSelection()
373 self.savedService = ref
374 self.session.openWithCallback(self.SingleServiceEPGClosed, EPGSelection, ref, serviceChangeCB=self.changeServiceCB)
376 def SingleServiceEPGClosed(self, ret=False):
377 self.setCurrentSelection(self.savedService)
379 def changeServiceCB(self, direction, epg):
380 beg = self.getCurrentSelection()
386 cur = self.getCurrentSelection()
387 if cur == beg or not (cur.flags & eServiceReference.isMarker):
389 epg.setService(ServiceReference(self.getCurrentSelection()))
391 class ChannelSelectionEdit:
393 self.entry_marked = False
394 self.movemode = False
395 self.bouquet_mark_edit = OFF
396 self.mutableList = None
398 self.saved_title = None
399 self.saved_root = None
401 class ChannelSelectionEditActionMap(ActionMap):
402 def __init__(self, csel, contexts = [ ], actions = { }, prio=0):
403 ActionMap.__init__(self, contexts, actions, prio)
406 def action(self, contexts, action):
407 if action == "cancel":
408 self.csel.handleEditCancel()
409 return 0 # fall-trough
411 return 0 # fall-trough
413 return ActionMap.action(self, contexts, action)
415 self["ChannelSelectEditActions"] = ChannelSelectionEditActionMap(self, ["ChannelSelectEditActions", "OkCancelActions"],
417 "contextMenu": self.doContext,
420 def getMutableList(self, root=eServiceReference()):
421 if not self.mutableList is None:
422 return self.mutableList
423 serviceHandler = eServiceCenter.getInstance()
426 list = root and serviceHandler.list(root)
428 return list.startEdit()
431 def buildBouquetID(self, str):
435 if (c >= 'a' and c <= 'z') or (c >= '0' and c <= '9'):
441 def addMarker(self, name):
442 current = self.servicelist.getCurrent()
443 mutableList = self.getMutableList()
446 str = '1:64:%d:0:0:0:0:0:0:0::%s'%(cnt, name)
447 ref = eServiceReference(str)
448 if current and current.valid():
449 if not mutableList.addService(ref, current):
450 self.servicelist.addService(ref, True)
451 mutableList.flushChanges()
453 elif not mutableList.addService(ref):
454 self.servicelist.addService(ref, True)
455 mutableList.flushChanges()
459 def addAlternativeServices(self):
460 cur_service = ServiceReference(self.getCurrentSelection())
461 root = self.getRoot()
462 cur_root = root and ServiceReference(root)
463 mutableBouquet = cur_root.list().startEdit()
465 name = cur_service.getServiceName()
467 if self.mode == MODE_TV:
468 str = '1:134:1:0:0:0:0:0:0:0:FROM BOUQUET \"alternatives.%s.tv\" ORDER BY bouquet'%(self.buildBouquetID(name))
470 str = '1:134:2:0:0:0:0:0:0:0:FROM BOUQUET \"alternatives.%s.radio\" ORDER BY bouquet'%(self.buildBouquetID(name))
471 new_ref = ServiceReference(str)
472 if not mutableBouquet.addService(new_ref.ref, cur_service.ref):
473 mutableBouquet.removeService(cur_service.ref)
474 mutableBouquet.flushChanges()
475 eDVBDB.getInstance().reloadBouquets()
476 mutableAlternatives = new_ref.list().startEdit()
477 if mutableAlternatives:
478 mutableAlternatives.setListName(name)
479 if mutableAlternatives.addService(cur_service.ref):
480 print "add", cur_service.ref.toString(), "to new alternatives failed"
481 mutableAlternatives.flushChanges()
482 self.servicelist.addService(new_ref.ref, True)
483 self.servicelist.removeCurrent()
484 self.servicelist.moveUp()
486 print "get mutable list for new created alternatives failed"
488 print "add", str, "to", cur_root.getServiceName(), "failed"
490 print "bouquetlist is not editable"
492 def addBouquet(self, bName, services):
493 serviceHandler = eServiceCenter.getInstance()
494 mutableBouquetList = serviceHandler.list(self.bouquet_root).startEdit()
495 if mutableBouquetList:
496 if self.mode == MODE_TV:
498 str = '1:7:1:0:0:0:0:0:0:0:FROM BOUQUET \"userbouquet.%s.tv\" ORDER BY bouquet'%(self.buildBouquetID(bName))
501 str = '1:7:2:0:0:0:0:0:0:0:FROM BOUQUET \"userbouquet.%s.radio\" ORDER BY bouquet'%(self.buildBouquetID(bName))
502 new_bouquet_ref = eServiceReference(str)
503 if not mutableBouquetList.addService(new_bouquet_ref):
504 mutableBouquetList.flushChanges()
505 eDVBDB.getInstance().reloadBouquets()
506 mutableBouquet = serviceHandler.list(new_bouquet_ref).startEdit()
508 mutableBouquet.setListName(bName)
509 if services is not None:
510 for service in services:
511 if mutableBouquet.addService(service):
512 print "add", service.toString(), "to new bouquet failed"
513 mutableBouquet.flushChanges()
515 print "get mutable list for new created bouquet failed"
516 # do some voodoo to check if current_root is equal to bouquet_root
517 cur_root = self.getRoot();
518 str1 = cur_root and cur_root.toString()
519 pos1 = str1 and str1.find("FROM BOUQUET") or -1
520 pos2 = self.bouquet_rootstr.find("FROM BOUQUET")
521 if pos1 != -1 and pos2 != -1 and str1[pos1:] == self.bouquet_rootstr[pos2:]:
522 self.servicelist.addService(new_bouquet_ref)
524 print "add", str, "to bouquets failed"
526 print "bouquetlist is not editable"
528 def copyCurrentToBouquetList(self):
529 provider = ServiceReference(self.getCurrentSelection())
530 providerName = provider.getServiceName()
531 serviceHandler = eServiceCenter.getInstance()
532 services = serviceHandler.list(provider.ref)
533 self.addBouquet(providerName, services and services.getContent('R', True))
535 def removeAlternativeServices(self):
536 cur_service = ServiceReference(self.getCurrentSelection())
537 root = self.getRoot()
538 cur_root = root and ServiceReference(root)
539 list = cur_service.list()
540 first_in_alternative = list and list.getNext()
541 if first_in_alternative:
542 edit_root = cur_root and cur_root.list().startEdit()
544 if not edit_root.addService(first_in_alternative, cur_service.ref):
545 self.servicelist.addService(first_in_alternative, True)
547 print "couldn't add first alternative service to current root"
549 print "couldn't edit current root!!"
551 print "remove empty alternative list !!"
553 self.servicelist.moveUp()
555 def removeBouquet(self):
556 refstr = self.getCurrentSelection().toString()
557 print "removeBouquet", refstr
558 self.bouquetNumOffsetCache = { }
559 pos = refstr.find('FROM BOUQUET "')
562 refstr = refstr[pos+14:]
563 pos = refstr.find('"')
565 filename = eEnv.resolve('${sysconfdir}/enigma2/') + refstr[:pos]
566 self.removeCurrentService()
568 if filename is not None:
571 print "error during remove of", filename
573 def removeSatelliteServices(self):
574 current = self.getCurrentSelection()
575 unsigned_orbpos = current.getUnsignedData(4) >> 16
576 if unsigned_orbpos == 0XFFFF:
577 msg = _("Are you sure to remove all cable services?")
578 elif unsigned_orbpos == 0XEEEE:
579 msg = _("Are you sure to remove all terrestrial services?")
581 orbpos = current.getData(4) >> 16
583 service_name = str(nimmanager.getSatDescription(orbpos))
585 if orbpos > 1800: # west
586 orbpos = 3600 - orbpos
590 service_name = ("%d.%d" + h) % (orbpos / 10, orbpos % 10)
591 msg = _("Are you sure to remove all %s services?" % service_name)
592 self.session.openWithCallback(self.removeSatelliteServicesCallback, MessageBox, msg)
594 def removeSatelliteServicesCallback(self, res):
598 currentIndex = self.servicelist.getCurrentIndex()
599 current = self.getCurrentSelection()
600 unsigned_orbpos = current.getUnsignedData(4) >> 16
601 if unsigned_orbpos == 0XFFFF:
602 eDVBDB.getInstance().removeServices(0xFFFF0000 - 0x100000000)
603 elif unsigned_orbpos == 0XEEEE:
604 eDVBDB.getInstance().removeServices(0xEEEE0000 - 0x100000000)
606 curpath = self.getCurrentSelection().getPath()
607 idx = curpath.find("satellitePosition == ")
609 tmp = curpath[idx+21:]
612 satpos = int(tmp[:idx])
613 eDVBDB.getInstance().removeServices(-1, -1, -1, satpos)
615 if hasattr(self, 'setMode') and hasattr(self, 'showSatellites'):
617 self.showSatellites()
618 self.servicelist.moveToIndex(currentIndex)
619 if currentIndex != self.servicelist.getCurrentIndex():
620 self.servicelist.instance.moveSelection(self.servicelist.instance.moveEnd)
622 # multiple marked entry stuff ( edit mode, later multiepg selection )
623 def startMarkedEdit(self, type):
624 self.savedPath = self.servicePath[:]
625 if type == EDIT_ALTERNATIVES:
626 self.enterPath(self.getCurrentSelection())
627 self.mutableList = self.getMutableList()
628 # add all services from the current list to internal marked set in listboxservicecontent
629 self.clearMarks() # this clears the internal marked set in the listboxservicecontent
630 self.saved_title = self.getTitle()
631 pos = self.saved_title.find(')')
632 new_title = self.saved_title[:pos+1]
633 if type == EDIT_ALTERNATIVES:
634 self.bouquet_mark_edit = EDIT_ALTERNATIVES
635 new_title += ' ' + _("[alternative edit]")
637 self.bouquet_mark_edit = EDIT_BOUQUET
638 if config.usage.multibouquet.value:
639 new_title += ' ' + _("[bouquet edit]")
641 new_title += ' ' + _("[favourite edit]")
642 self.setTitle(new_title)
643 self.__marked = self.servicelist.getRootServices()
644 for x in self.__marked:
645 self.servicelist.addMarked(eServiceReference(x))
646 self.showAllServices()
648 def endMarkedEdit(self, abort):
649 if not abort and self.mutableList is not None:
650 self.bouquetNumOffsetCache = { }
651 new_marked = set(self.servicelist.getMarked())
652 old_marked = set(self.__marked)
653 removed = old_marked - new_marked
654 added = new_marked - old_marked
658 self.mutableList.removeService(eServiceReference(x))
661 self.mutableList.addService(eServiceReference(x))
663 self.mutableList.flushChanges()
666 self.bouquet_mark_edit = OFF
667 self.mutableList = None
668 self.setTitle(self.saved_title)
669 self.saved_title = None
670 # self.servicePath is just a reference to servicePathTv or Radio...
671 # so we never ever do use the asignment operator in self.servicePath
672 del self.servicePath[:] # remove all elements
673 self.servicePath += self.savedPath # add saved elements
675 self.setRoot(self.servicePath[-1])
677 def clearMarks(self):
678 self.servicelist.clearMarks()
681 ref = self.servicelist.getCurrent()
682 if self.servicelist.isMarked(ref):
683 self.servicelist.removeMarked(ref)
685 self.servicelist.addMarked(ref)
687 def removeCurrentService(self):
688 ref = self.servicelist.getCurrent()
689 mutableList = self.getMutableList()
690 if ref.valid() and mutableList is not None:
691 if not mutableList.removeService(ref):
692 self.bouquetNumOffsetCache = { }
693 mutableList.flushChanges() #FIXME dont flush on each single removed service
694 self.servicelist.removeCurrent()
696 def addServiceToBouquet(self, dest, service=None):
697 mutableList = self.getMutableList(dest)
698 if not mutableList is None:
699 if service is None: #use current selected service
700 service = self.servicelist.getCurrent()
701 if not mutableList.addService(service):
702 self.bouquetNumOffsetCache = { }
703 mutableList.flushChanges()
704 # do some voodoo to check if current_root is equal to dest
705 cur_root = self.getRoot();
706 str1 = cur_root and cur_root.toString() or -1
707 str2 = dest.toString()
708 pos1 = str1.find("FROM BOUQUET")
709 pos2 = str2.find("FROM BOUQUET")
710 if pos1 != -1 and pos2 != -1 and str1[pos1:] == str2[pos2:]:
711 self.servicelist.addService(service)
713 def toggleMoveMode(self):
715 if self.entry_marked:
716 self.toggleMoveMarked() # unmark current entry
717 self.movemode = False
718 self.pathChangeDisabled = False # re-enable path change
719 self.mutableList.flushChanges() # FIXME add check if changes was made
720 self.mutableList = None
721 self.setTitle(self.saved_title)
722 self.saved_title = None
723 cur_root = self.getRoot()
724 if cur_root and cur_root == self.bouquet_root:
725 self.bouquetNumOffsetCache = { }
727 self.mutableList = self.getMutableList()
729 self.pathChangeDisabled = True # no path change allowed in movemode
730 self.saved_title = self.getTitle()
731 new_title = self.saved_title
732 pos = self.saved_title.find(')')
733 new_title = self.saved_title[:pos+1] + ' ' + _("[move mode]") + self.saved_title[pos+1:]
734 self.setTitle(new_title);
736 def handleEditCancel(self):
737 if self.movemode: #movemode active?
738 self.channelSelected() # unmark
739 self.toggleMoveMode() # disable move mode
740 elif self.bouquet_mark_edit != OFF:
741 self.endMarkedEdit(True) # abort edit mode
743 def toggleMoveMarked(self):
744 if self.entry_marked:
745 self.servicelist.setCurrentMarked(False)
746 self.entry_marked = False
748 self.servicelist.setCurrentMarked(True)
749 self.entry_marked = True
752 self.session.openWithCallback(self.exitContext, ChannelContextMenu, self)
754 def exitContext(self, close = False):
761 # type 1 = digital television service
762 # type 4 = nvod reference service (NYI)
763 # type 17 = MPEG-2 HD digital television service
764 # type 22 = advanced codec SD digital television
765 # type 24 = advanced codec SD NVOD reference service (NYI)
766 # type 25 = advanced codec HD digital television
767 # type 27 = advanced codec HD NVOD reference service (NYI)
768 # type 2 = digital radio sound service
769 # type 10 = advanced codec digital radio sound service
770 # type 31 = High Efficiency Video Coing digital television
772 service_types_tv = '1:7:1:0:0:0:0:0:0:0:(type == 1) || (type == 17) || (type == 22) || (type == 25) || (type == 31) || (type == 134) || (type == 195)'
773 service_types_radio = '1:7:2:0:0:0:0:0:0:0:(type == 2) || (type == 10)'
775 class ChannelSelectionBase(Screen):
776 def __init__(self, session):
777 Screen.__init__(self, session)
779 self["key_red"] = Button(_("All"))
780 self["key_green"] = Button(_("Satellites"))
781 self["key_yellow"] = Button(_("Provider"))
782 self["key_blue"] = Button(_("Favourites"))
784 self["list"] = ServiceList()
785 self.servicelist = self["list"]
787 self.numericalTextInput = NumericalTextInput()
788 self.numericalTextInput.setUseableChars(u'1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ')
790 self.servicePathTV = [ ]
791 self.servicePathRadio = [ ]
792 self.servicePath = [ ]
793 self.rootChanged = False
797 self.pathChangeDisabled = False
799 self.bouquetNumOffsetCache = { }
801 self["ChannelSelectBaseActions"] = NumberActionMap(["ChannelSelectBaseActions", "NumberActions", "InputAsciiActions"],
803 "showFavourites": self.showFavourites,
804 "showAllServices": self.showAllServices,
805 "showProviders": self.showProviders,
806 "showSatellites": self.showSatellites,
807 "nextBouquet": self.nextBouquet,
808 "prevBouquet": self.prevBouquet,
809 "nextMarker": self.nextMarker,
810 "prevMarker": self.prevMarker,
811 "gotAsciiCode": self.keyAsciiCode,
812 "1": self.keyNumberGlobal,
813 "2": self.keyNumberGlobal,
814 "3": self.keyNumberGlobal,
815 "4": self.keyNumberGlobal,
816 "5": self.keyNumberGlobal,
817 "6": self.keyNumberGlobal,
818 "7": self.keyNumberGlobal,
819 "8": self.keyNumberGlobal,
820 "9": self.keyNumberGlobal,
823 self.recallBouquetMode()
825 def getBouquetNumOffset(self, bouquet):
826 if not config.usage.multibouquet.value:
828 str = bouquet.toString()
830 if not self.bouquetNumOffsetCache.has_key(str):
831 serviceHandler = eServiceCenter.getInstance()
832 bouquetlist = serviceHandler.list(self.bouquet_root)
833 if not bouquetlist is None:
835 bouquetIterator = bouquetlist.getNext()
836 if not bouquetIterator.valid(): #end of list
838 self.bouquetNumOffsetCache[bouquetIterator.toString()]=offsetCount
839 if not (bouquetIterator.flags & eServiceReference.isDirectory):
841 servicelist = serviceHandler.list(bouquetIterator)
842 if not servicelist is None:
844 serviceIterator = servicelist.getNext()
845 if not serviceIterator.valid(): #check if end of list
847 playable = not (serviceIterator.flags & (eServiceReference.isDirectory|eServiceReference.isMarker))
850 return self.bouquetNumOffsetCache.get(str, offsetCount)
852 def recallBouquetMode(self):
853 if self.mode == MODE_TV:
854 self.service_types = service_types_tv
855 if config.usage.multibouquet.value:
856 self.bouquet_rootstr = '1:7:1:0:0:0:0:0:0:0:FROM BOUQUET "bouquets.tv" ORDER BY bouquet'
858 self.bouquet_rootstr = '%s FROM BOUQUET "userbouquet.favourites.tv" ORDER BY bouquet'%(self.service_types)
860 self.service_types = service_types_radio
861 if config.usage.multibouquet.value:
862 self.bouquet_rootstr = '1:7:1:0:0:0:0:0:0:0:FROM BOUQUET "bouquets.radio" ORDER BY bouquet'
864 self.bouquet_rootstr = '%s FROM BOUQUET "userbouquet.favourites.radio" ORDER BY bouquet'%(self.service_types)
865 self.bouquet_root = eServiceReference(self.bouquet_rootstr)
869 self.servicePath = self.servicePathTV
870 self.recallBouquetMode()
871 title = self.getTitle()
872 pos = title.find(" (")
878 def setRadioMode(self):
879 self.mode = MODE_RADIO
880 self.servicePath = self.servicePathRadio
881 self.recallBouquetMode()
882 title = self.getTitle()
883 pos = title.find(" (")
889 def setRoot(self, root, justSet=False):
890 path = root.getPath()
891 inBouquetRootList = path.find('FROM BOUQUET "bouquets.') != -1 #FIXME HACK
892 pos = path.find('FROM BOUQUET')
893 isBouquet = (pos != -1) and (root.flags & eServiceReference.isDirectory)
894 if not inBouquetRootList and isBouquet:
895 self.servicelist.setMode(ServiceList.MODE_FAVOURITES)
896 self.servicelist.setNumberOffset(self.getBouquetNumOffset(root))
898 self.servicelist.setMode(ServiceList.MODE_NORMAL)
899 self.servicelist.setRoot(root, justSet)
900 self.rootChanged = True
901 self.buildTitleString()
903 def removeModeStr(self, str):
904 if self.mode == MODE_TV:
905 pos = str.find(' (TV)')
907 pos = str.find(' (Radio)')
912 def getServiceName(self, ref):
913 str = self.removeModeStr(ServiceReference(ref).getServiceName())
915 pathstr = ref.getPath()
916 if 'FROM PROVIDERS' in pathstr:
918 if 'FROM SATELLITES' in pathstr:
919 return _("Satellites")
920 if ') ORDER BY name' in pathstr:
924 def buildTitleString(self):
925 titleStr = self.getTitle()
926 pos = titleStr.find(']')
928 pos = titleStr.find(')')
930 titleStr = titleStr[:pos+1]
931 Len = len(self.servicePath)
933 base_ref = self.servicePath[0]
935 end_ref = self.servicePath[Len-1]
938 nameStr = self.getServiceName(base_ref)
939 titleStr += ' ' + nameStr
940 if end_ref is not None:
945 nameStr = self.getServiceName(end_ref)
947 self.setTitle(titleStr)
950 self.servicelist.moveUp()
953 self.servicelist.moveDown()
956 del self.servicePath[:]
958 def enterPath(self, ref, justSet=False):
959 self.servicePath.append(ref)
960 self.setRoot(ref, justSet)
962 def pathUp(self, justSet=False):
963 prev = self.servicePath.pop()
965 current = self.servicePath[-1]
966 self.setRoot(current, justSet)
968 self.setCurrentSelection(prev)
971 def isBasePathEqual(self, ref):
972 if len(self.servicePath) > 1 and self.servicePath[0] == ref:
976 def isPrevPathEqual(self, ref):
977 length = len(self.servicePath)
978 if length > 1 and self.servicePath[length-2] == ref:
982 def preEnterPath(self, refstr):
985 def showAllServices(self):
986 if not self.pathChangeDisabled:
987 refstr = '%s ORDER BY name'%(self.service_types)
988 if not self.preEnterPath(refstr):
989 ref = eServiceReference(refstr)
990 currentRoot = self.getRoot()
991 if currentRoot is None or currentRoot != ref:
995 def showSatellites(self):
996 if not self.pathChangeDisabled:
997 refstr = '%s FROM SATELLITES ORDER BY satellitePosition'%(self.service_types)
998 if not self.preEnterPath(refstr):
999 ref = eServiceReference(refstr)
1003 if self.isBasePathEqual(ref):
1004 if self.isPrevPathEqual(ref):
1006 prev = self.pathUp(justSet)
1008 currentRoot = self.getRoot()
1009 if currentRoot is None or currentRoot != ref:
1012 self.enterPath(ref, True)
1014 serviceHandler = eServiceCenter.getInstance()
1015 servicelist = serviceHandler.list(ref)
1016 if not servicelist is None:
1018 service = servicelist.getNext()
1019 if not service.valid(): #check if end of list
1021 unsigned_orbpos = service.getUnsignedData(4) >> 16
1022 orbpos = service.getData(4) >> 16
1025 if service.getPath().find("FROM PROVIDER") != -1:
1026 service_type = _("Providers")
1027 elif service.getPath().find("flags == %d" %(FLAG_SERVICE_NEW_FOUND)) != -1:
1028 service_type = _("New")
1030 service_type = _("Services")
1032 # why we need this cast?
1033 service_name = str(nimmanager.getSatDescription(orbpos))
1035 if unsigned_orbpos == 0xFFFF: #Cable
1036 service_name = _("Cable")
1037 elif unsigned_orbpos == 0xEEEE: #Terrestrial
1038 service_name = _("Terrestrial")
1040 if orbpos > 1800: # west
1041 orbpos = 3600 - orbpos
1045 service_name = ("%d.%d" + h) % (orbpos / 10, orbpos % 10)
1046 service.setName("%s - %s" % (service_name, service_type))
1047 self.servicelist.addService(service)
1048 cur_ref = self.session.nav.getCurrentlyPlayingServiceReference()
1050 pos = self.service_types.rfind(':')
1051 refstr = '%s (channelID == %08x%04x%04x) && %s ORDER BY name' %(self.service_types[:pos+1],
1052 cur_ref.getUnsignedData(4), # NAMESPACE
1053 cur_ref.getUnsignedData(2), # TSID
1054 cur_ref.getUnsignedData(3), # ONID
1055 self.service_types[pos+1:])
1056 ref = eServiceReference(refstr)
1057 ref.setName(_("Current Transponder"))
1058 self.servicelist.addService(ref)
1059 self.servicelist.finishFill()
1060 if prev is not None:
1061 self.setCurrentSelection(prev)
1063 def showProviders(self):
1064 if not self.pathChangeDisabled:
1065 refstr = '%s FROM PROVIDERS ORDER BY name'%(self.service_types)
1066 if not self.preEnterPath(refstr):
1067 ref = eServiceReference(refstr)
1068 if self.isBasePathEqual(ref):
1071 currentRoot = self.getRoot()
1072 if currentRoot is None or currentRoot != ref:
1076 def changeBouquet(self, direction):
1077 if not self.pathChangeDisabled:
1078 if len(self.servicePath) > 1:
1079 #when enter satellite root list we must do some magic stuff..
1080 ref = eServiceReference('%s FROM SATELLITES ORDER BY satellitePosition'%(self.service_types))
1081 if self.isBasePathEqual(ref):
1082 self.showSatellites()
1089 ref = self.getCurrentSelection()
1092 def inBouquet(self):
1093 if self.servicePath and self.servicePath[0] == self.bouquet_root:
1098 return self.servicelist.atBegin()
1101 return self.servicelist.atEnd()
1103 def nextBouquet(self):
1104 self.changeBouquet(+1)
1106 def prevBouquet(self):
1107 self.changeBouquet(-1)
1109 def showFavourites(self):
1110 if not self.pathChangeDisabled:
1111 if not self.preEnterPath(self.bouquet_rootstr):
1112 if self.isBasePathEqual(self.bouquet_root):
1115 currentRoot = self.getRoot()
1116 if currentRoot is None or currentRoot != self.bouquet_root:
1118 self.enterPath(self.bouquet_root)
1120 def keyNumberGlobal(self, number):
1121 unichar = self.numericalTextInput.getKey(number)
1122 charstr = unichar.encode("utf-8")
1123 if len(charstr) == 1:
1124 self.servicelist.moveToChar(charstr[0])
1126 def keyAsciiCode(self):
1127 #unichar = unichr(getPrevAsciiCode())
1128 from Components.config import getCharValue
1129 unichar = getCharValue(getPrevAsciiCode())
1132 if len(str(unichar)) > 1:
1134 charstr = unichar.encode("utf-8")
1135 if len(charstr) == 1:
1136 self.servicelist.moveToChar(charstr[0])
1139 return self.servicelist.getRoot()
1141 def getCurrentSelection(self):
1142 return self.servicelist.getCurrent()
1144 def setCurrentSelection(self, service):
1145 self.servicelist.setCurrent(service)
1147 def getBouquetList(self):
1149 serviceHandler = eServiceCenter.getInstance()
1150 if config.usage.multibouquet.value:
1151 list = serviceHandler.list(self.bouquet_root)
1157 if s.flags & eServiceReference.isDirectory:
1158 info = serviceHandler.info(s)
1160 bouquets.append((info.getName(s), s))
1163 info = serviceHandler.info(self.bouquet_root)
1165 bouquets.append((info.getName(self.bouquet_root), self.bouquet_root))
1169 def keyNumber0(self, num):
1170 if len(self.servicePath) > 1:
1173 self.keyNumberGlobal(num)
1176 if len(self.servicePath) > 1:
1177 if self.isBasePathEqual(self.bouquet_root):
1178 self.showFavourites()
1180 ref = eServiceReference('%s FROM SATELLITES ORDER BY satellitePosition'%(self.service_types))
1181 if self.isBasePathEqual(ref):
1182 self.showSatellites()
1184 ref = eServiceReference('%s FROM PROVIDERS ORDER BY name'%(self.service_types))
1185 if self.isBasePathEqual(ref):
1186 self.showProviders()
1188 self.showAllServices()
1190 def nextMarker(self):
1191 self.servicelist.moveToNextMarker()
1193 def prevMarker(self):
1194 self.servicelist.moveToPrevMarker()
1198 #config for lastservice
1199 config.tv = ConfigSubsection()
1200 config.tv.lastservice = ConfigText()
1201 config.tv.lastroot = ConfigText()
1202 config.radio = ConfigSubsection()
1203 config.radio.lastservice = ConfigText()
1204 config.radio.lastroot = ConfigText()
1205 config.servicelist = ConfigSubsection()
1206 config.servicelist.lastmode = ConfigText(default = "tv")
1208 class ChannelSelection(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelectionEPG, SelectionEventInfo):
1209 def __init__(self, session):
1210 ChannelSelectionBase.__init__(self,session)
1211 ChannelSelectionEdit.__init__(self)
1212 ChannelSelectionEPG.__init__(self)
1213 SelectionEventInfo.__init__(self)
1215 self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"],
1217 "cancel": self.cancel,
1218 "ok": self.channelSelected,
1219 "keyRadio": self.setModeRadio,
1220 "keyTV": self.setModeTv,
1223 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
1225 iPlayableService.evStart: self.__evServiceStart,
1226 iPlayableService.evEnd: self.__evServiceEnd
1229 self.lastChannelRootTimer = eTimer()
1230 self.lastChannelRootTimer.callback.append(self.__onCreate)
1231 self.lastChannelRootTimer.start(100,True)
1233 self.history_tv = [ ]
1234 self.history_radio = [ ]
1235 self.history = self.history_tv
1236 self.history_pos = 0
1238 self.lastservice = config.tv.lastservice
1239 self.lastroot = config.tv.lastroot
1240 self.revertMode = None
1241 config.usage.multibouquet.addNotifier(self.multibouquet_config_changed)
1242 self.new_service_played = False
1243 self.onExecBegin.append(self.asciiOn)
1246 rcinput = eRCInput.getInstance()
1247 rcinput.setKeyboardMode(rcinput.kmAscii)
1250 rcinput = eRCInput.getInstance()
1251 rcinput.setKeyboardMode(rcinput.kmNone)
1253 def multibouquet_config_changed(self, val):
1254 self.recallBouquetMode()
1256 def __evServiceStart(self):
1257 service = self.session.nav.getCurrentService()
1259 info = service.info()
1261 refstr = info.getInfoString(iServiceInformation.sServiceref)
1262 self.servicelist.setPlayableIgnoreService(eServiceReference(refstr))
1264 def __evServiceEnd(self):
1265 self.servicelist.setPlayableIgnoreService(eServiceReference())
1268 self.rootChanged = True
1270 lastservice=eServiceReference(self.lastservice.value)
1271 if lastservice.valid():
1272 self.setCurrentSelection(lastservice)
1274 def setModeTv(self):
1275 if self.revertMode is None and config.servicelist.lastmode.value == "radio":
1276 self.revertMode = MODE_RADIO
1277 self.history = self.history_tv
1278 self.lastservice = config.tv.lastservice
1279 self.lastroot = config.tv.lastroot
1280 config.servicelist.lastmode.value = "tv"
1284 def setModeRadio(self):
1285 if self.revertMode is None and config.servicelist.lastmode.value == "tv":
1286 self.revertMode = MODE_TV
1287 if config.usage.e1like_radio_mode.value:
1288 self.history = self.history_radio
1289 self.lastservice = config.radio.lastservice
1290 self.lastroot = config.radio.lastroot
1291 config.servicelist.lastmode.value = "radio"
1295 def __onCreate(self):
1296 if config.usage.e1like_radio_mode.value:
1297 if config.servicelist.lastmode.value == "tv":
1303 lastservice=eServiceReference(self.lastservice.value)
1304 if lastservice.valid():
1307 def channelSelected(self):
1308 ref = self.getCurrentSelection()
1310 self.toggleMoveMarked()
1311 elif (ref.flags & 7) == 7:
1313 elif self.bouquet_mark_edit != OFF:
1314 if not (self.bouquet_mark_edit == EDIT_ALTERNATIVES and ref.flags & eServiceReference.isGroup):
1316 elif not (ref.flags & eServiceReference.isMarker): # no marker
1317 root = self.getRoot()
1318 if not root or not (root.flags & eServiceReference.isGroup):
1323 #called from infoBar and channelSelected
1325 self.revertMode=None
1326 ref = self.session.nav.getCurrentlyPlayingServiceReference()
1327 nref = self.getCurrentSelection()
1328 if ref is None or ref != nref:
1329 self.new_service_played = True
1330 self.session.nav.playService(nref)
1332 self.saveChannel(nref)
1333 config.servicelist.lastmode.save()
1334 self.addToHistory(nref)
1336 def newServicePlayed(self):
1337 ret = self.new_service_played
1338 self.new_service_played = False
1341 def addToHistory(self, ref):
1342 if self.servicePath is not None:
1343 tmp=self.servicePath[:]
1346 del self.history[self.history_pos+1:]
1349 self.history.append(tmp)
1350 hlen = len(self.history)
1351 if hlen > HISTORYSIZE:
1354 self.history_pos = hlen-1
1356 def historyBack(self):
1357 hlen = len(self.history)
1358 if hlen > 1 and self.history_pos > 0:
1359 self.history_pos -= 1
1360 self.setHistoryPath()
1362 def historyNext(self):
1363 hlen = len(self.history)
1364 if hlen > 1 and self.history_pos < (hlen-1):
1365 self.history_pos += 1
1366 self.setHistoryPath()
1368 def setHistoryPath(self):
1369 path = self.history[self.history_pos][:]
1371 del self.servicePath[:]
1372 self.servicePath += path
1375 cur_root = self.getRoot()
1376 if cur_root and cur_root != root:
1378 self.session.nav.playService(ref)
1379 self.setCurrentSelection(ref)
1380 self.saveChannel(ref)
1384 for i in self.servicePath:
1385 path += i.toString()
1387 if path and path != self.lastroot.value:
1388 self.lastroot.value = path
1389 self.lastroot.save()
1391 def restoreRoot(self):
1392 tmp = [x for x in self.lastroot.value.split(';') if x != '']
1393 current = [x.toString() for x in self.servicePath]
1394 if tmp != current or self.rootChanged:
1398 self.servicePath.append(eServiceReference(i))
1401 path = self.servicePath.pop()
1402 self.enterPath(path)
1404 self.showFavourites()
1406 self.rootChanged = False
1408 def preEnterPath(self, refstr):
1409 if self.servicePath and self.servicePath[0] != eServiceReference(refstr):
1410 pathstr = self.lastroot.value
1411 if pathstr is not None and pathstr.find(refstr) == 0:
1413 lastservice=eServiceReference(self.lastservice.value)
1414 if lastservice.valid():
1415 self.setCurrentSelection(lastservice)
1419 def saveChannel(self, ref):
1421 refstr = ref.toString()
1424 if refstr != self.lastservice.value:
1425 self.lastservice.value = refstr
1426 self.lastservice.save()
1428 def setCurrentServicePath(self, path):
1430 self.history[self.history_pos] = path
1432 self.history.append(path)
1433 self.setHistoryPath()
1435 def getCurrentServicePath(self):
1437 return self.history[self.history_pos]
1440 def recallPrevService(self):
1441 hlen = len(self.history)
1443 if self.history_pos == hlen-1:
1444 tmp = self.history[self.history_pos]
1445 self.history[self.history_pos] = self.history[self.history_pos-1]
1446 self.history[self.history_pos-1] = tmp
1448 tmp = self.history[self.history_pos+1]
1449 self.history[self.history_pos+1] = self.history[self.history_pos]
1450 self.history[self.history_pos] = tmp
1451 self.setHistoryPath()
1454 if self.revertMode is None:
1456 lastservice=eServiceReference(self.lastservice.value)
1457 if lastservice.valid() and self.getCurrentSelection() != lastservice:
1458 self.setCurrentSelection(lastservice)
1459 elif self.revertMode == MODE_TV:
1461 elif self.revertMode == MODE_RADIO:
1463 self.revertMode = None
1467 class RadioInfoBar(Screen):
1468 def __init__(self, session):
1469 Screen.__init__(self, session)
1470 self["RdsDecoder"] = RdsDecoder(self.session.nav)
1472 class ChannelSelectionRadio(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelectionEPG, InfoBarBase):
1473 ALLOW_SUSPEND = True
1475 def __init__(self, session, infobar):
1476 ChannelSelectionBase.__init__(self, session)
1477 ChannelSelectionEdit.__init__(self)
1478 ChannelSelectionEPG.__init__(self)
1479 InfoBarBase.__init__(self)
1480 self.infobar = infobar
1481 self.onLayoutFinish.append(self.onCreate)
1483 self.info = session.instantiateDialog(RadioInfoBar) # our simple infobar
1484 self.info.setAnimationMode(0)
1486 self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"],
1488 "keyTV": self.cancel,
1489 "keyRadio": self.cancel,
1490 "cancel": self.cancel,
1491 "ok": self.channelSelected,
1494 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
1496 iPlayableService.evStart: self.__evServiceStart,
1497 iPlayableService.evEnd: self.__evServiceEnd
1500 ########## RDS Radiotext / Rass Support BEGIN
1501 self.infobar = infobar # reference to real infobar (the one and only)
1502 self["RdsDecoder"] = self.info["RdsDecoder"]
1503 self["RdsActions"] = HelpableActionMap(self, "InfobarRdsActions",
1505 "startRassInteractive": (self.startRassInteractive, _("View Rass interactive..."))
1507 self["RdsActions"].setEnabled(False)
1508 infobar.rds_display.onRassInteractivePossibilityChanged.append(self.RassInteractivePossibilityChanged)
1509 self.onClose.append(self.__onClose)
1511 def __onClose(self):
1512 lastservice=eServiceReference(config.tv.lastservice.value)
1513 self.session.nav.playService(lastservice)
1515 def startRassInteractive(self):
1517 self.infobar.rass_interactive = self.session.openWithCallback(self.RassInteractiveClosed, RassInteractive)
1519 def RassInteractiveClosed(self):
1521 self.infobar.rass_interactive = None
1522 self.infobar.RassSlidePicChanged()
1524 def RassInteractivePossibilityChanged(self, state):
1525 self["RdsActions"].setEnabled(state)
1526 ########## RDS Radiotext / Rass Support END
1529 self.infobar.rds_display.onRassInteractivePossibilityChanged.remove(self.RassInteractivePossibilityChanged)
1531 #set previous tv service
1534 def __evServiceStart(self):
1535 service = self.session.nav.getCurrentService()
1537 info = service.info()
1539 refstr = info.getInfoString(iServiceInformation.sServiceref)
1540 self.servicelist.setPlayableIgnoreService(eServiceReference(refstr))
1542 def __evServiceEnd(self):
1543 self.servicelist.setPlayableIgnoreService(eServiceReference())
1547 for i in self.servicePathRadio:
1548 path += i.toString()
1550 if path and path != config.radio.lastroot.value:
1551 config.radio.lastroot.value = path
1552 config.radio.lastroot.save()
1554 def restoreRoot(self):
1555 tmp = [x for x in config.radio.lastroot.value.split(';') if x != '']
1556 current = [x.toString() for x in self.servicePath]
1557 if tmp != current or self.rootChanged:
1560 self.servicePathRadio.append(eServiceReference(i))
1563 path = self.servicePathRadio.pop()
1564 self.enterPath(path)
1566 self.showFavourites()
1568 self.rootChanged = False
1570 def preEnterPath(self, refstr):
1571 if self.servicePathRadio and self.servicePathRadio[0] != eServiceReference(refstr):
1572 pathstr = config.radio.lastroot.value
1573 if pathstr is not None and pathstr.find(refstr) == 0:
1575 lastservice=eServiceReference(config.radio.lastservice.value)
1576 if lastservice.valid():
1577 self.setCurrentSelection(lastservice)
1584 lastservice=eServiceReference(config.radio.lastservice.value)
1585 if lastservice.valid():
1586 self.servicelist.setCurrent(lastservice)
1587 self.session.nav.playService(lastservice)
1589 self.session.nav.stopService()
1592 def channelSelected(self): # just return selected service
1593 ref = self.getCurrentSelection()
1595 self.toggleMoveMarked()
1596 elif (ref.flags & 7) == 7:
1598 elif self.bouquet_mark_edit != OFF:
1599 if not (self.bouquet_mark_edit == EDIT_ALTERNATIVES and ref.flags & eServiceReference.isGroup):
1601 elif not (ref.flags & eServiceReference.isMarker): # no marker
1602 cur_root = self.getRoot()
1603 if not cur_root or not (cur_root.flags & eServiceReference.isGroup):
1604 playingref = self.session.nav.getCurrentlyPlayingServiceReference()
1605 if playingref is None or playingref != ref:
1606 self.session.nav.playService(ref)
1607 config.radio.lastservice.value = ref.toString()
1608 config.radio.lastservice.save()
1611 class SimpleChannelSelection(ChannelSelectionBase):
1612 def __init__(self, session, title):
1613 ChannelSelectionBase.__init__(self, session)
1614 self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"],
1616 "cancel": self.close,
1617 "ok": self.channelSelected,
1618 "keyRadio": self.setModeRadio,
1619 "keyTV": self.setModeTv,
1622 self.onLayoutFinish.append(self.layoutFinished)
1624 def layoutFinished(self):
1627 def channelSelected(self): # just return selected service
1628 ref = self.getCurrentSelection()
1629 if (ref.flags & 7) == 7:
1631 elif not (ref.flags & eServiceReference.isMarker):
1632 ref = self.getCurrentSelection()
1635 def setModeTv(self):
1637 self.showFavourites()
1639 def setModeRadio(self):
1641 self.showFavourites()