1 from Tools.Profile import profile
3 from Screen import Screen
5 import Components.ParentalControl
6 from Components.Button import Button
7 from Components.ServiceList import ServiceList, refreshServiceList
8 from Components.ActionMap import NumberActionMap, ActionMap, HelpableActionMap
9 from Components.MenuList import MenuList
10 from Components.ServiceEventTracker import ServiceEventTracker, InfoBarBase
11 profile("ChannelSelection.py 1")
12 from EpgSelection import EPGSelection
13 from enigma import eServiceReference, eEPGCache, eServiceCenter, eRCInput, eTimer, eDVBDB, iPlayableService, iServiceInformation, getPrevAsciiCode, eEnv
14 from Components.config import config, configfile, ConfigSubsection, ConfigText, ConfigYesNo
15 from Tools.NumericalTextInput import NumericalTextInput
16 profile("ChannelSelection.py 2")
17 from Components.NimManager import nimmanager
18 profile("ChannelSelection.py 2.1")
19 from Components.Sources.RdsDecoder import RdsDecoder
20 profile("ChannelSelection.py 2.2")
21 from Components.Sources.ServiceEvent import ServiceEvent
22 from Components.Sources.Event import Event
23 profile("ChannelSelection.py 2.3")
24 from Components.Input import Input
25 profile("ChannelSelection.py 3")
26 from Components.ChoiceList import ChoiceList, ChoiceEntryComponent
27 from Components.SystemInfo import SystemInfo
28 from Screens.InputBox import PinInput
29 from Screens.VirtualKeyBoard import VirtualKeyBoard
30 from Screens.MessageBox import MessageBox
31 from Screens.ServiceInfo import ServiceInfo
32 from Screens.Hotkey import InfoBarHotkey, hotkeyActionMap, getHotkeyFunctions
33 profile("ChannelSelection.py 4")
34 from Screens.PictureInPicture import PictureInPicture
35 from Screens.RdsDisplay import RassInteractive
36 from ServiceReference import ServiceReference
37 from Tools.BoundFunction import boundFunction
38 from Tools import Notifications
39 from Tools.Alternatives import CompareWithAlternatives
40 from Tools.Directories import fileExists
41 from Plugins.Plugin import PluginDescriptor
42 from Components.PluginComponent import plugins
43 from Screens.ChoiceBox import ChoiceBox
44 from Screens.EventView import EventViewEPGSelect
46 profile("ChannelSelection.py after imports")
48 FLAG_SERVICE_NEW_FOUND = 64
49 FLAG_IS_DEDICATED_3D = 128 #define in lib/dvb/idvb.h as dxNewFound = 64 and dxIsDedicated3D = 128
51 class BouquetSelector(Screen):
52 def __init__(self, session, bouquets, selectedFunc, enableWrapAround=True):
53 Screen.__init__(self, session)
55 self.selectedFunc=selectedFunc
57 self["actions"] = ActionMap(["OkCancelActions"],
59 "ok": self.okbuttonClick,
60 "cancel": self.cancelClick
62 entrys = [ (x[0], x[1]) for x in bouquets ]
63 self["menu"] = MenuList(entrys, enableWrapAround)
66 cur = self["menu"].getCurrent()
69 def okbuttonClick(self):
70 self.selectedFunc(self.getCurrent())
78 def cancelClick(self):
81 class SilentBouquetSelector:
82 def __init__(self, bouquets, enableWrapAround=False, current=0):
83 self.bouquets = [b[1] for b in bouquets]
85 self.count = len(bouquets)
86 self.enableWrapAround = enableWrapAround
89 if self.pos > 0 or self.enableWrapAround:
90 self.pos = (self.pos - 1) % self.count
93 if self.pos < (self.count - 1) or self.enableWrapAround:
94 self.pos = (self.pos + 1) % self.count
97 return self.bouquets[self.pos]
99 # csel.bouquet_mark_edit values
102 EDIT_ALTERNATIVES = 2
104 def append_when_current_valid(current, menu, args, level=0, key=""):
105 if current and current.valid() and level <= config.usage.setup_level.index:
106 menu.append(ChoiceEntryComponent(key, args))
108 def removed_userbouquets_available():
109 for file in os.listdir("/etc/enigma2/"):
110 if file.startswith("userbouquet") and file.endswith(".del"):
114 class ChannelContextMenu(Screen):
115 def __init__(self, session, csel):
117 Screen.__init__(self, session)
120 if self.isProtected():
121 self.onFirstExecBegin.append(boundFunction(self.session.openWithCallback, self.protectResult, PinInput, pinList=[x.value for x in config.ParentalControl.servicepin], triesEntry=config.ParentalControl.retries.servicepin, title=_("Please enter the correct pin code"), windowTitle=_("Enter pin code")))
123 self["actions"] = ActionMap(["OkCancelActions", "ColorActions", "NumberActions", "MenuActions"],
125 "ok": self.okbuttonClick,
126 "cancel": self.cancelClick,
127 "blue": self.showServiceInPiP,
128 "red": self.playMain,
129 "menu": self.openSetup,
130 "2": self.renameEntry,
131 "3": self.findCurrentlyPlayed,
132 "5": self.addServiceToBouquetOrAlternative,
133 "6": self.toggleMoveModeSelect,
134 "8": self.removeEntry
138 self.removeFunction = False
139 self.addFunction = False
140 current = csel.getCurrentSelection()
141 current_root = csel.getRoot()
142 current_sel_path = current.getPath()
143 current_sel_flags = current.flags
144 inBouquetRootList = current_root and 'FROM BOUQUET "bouquets.' in current_root.getPath() #FIXME HACK
145 inAlternativeList = current_root and 'FROM BOUQUET "alternatives' in current_root.getPath()
146 self.inBouquet = csel.getMutableList() is not None
147 haveBouquets = config.usage.multibouquet.value
148 from Components.ParentalControl import parentalControl
149 self.parentalControl = parentalControl
150 self.parentalControlEnabled = config.ParentalControl.servicepinactive.value
151 if not (current_sel_path or current_sel_flags & (eServiceReference.isDirectory|eServiceReference.isMarker)):
152 append_when_current_valid(current, menu, (_("show transponder info"), self.showServiceInformations), level=2)
153 if csel.bouquet_mark_edit == OFF and not csel.entry_marked:
154 if not inBouquetRootList:
155 isPlayable = not (current_sel_flags & (eServiceReference.isMarker|eServiceReference.isDirectory))
157 for p in plugins.getPlugins(PluginDescriptor.WHERE_CHANNEL_CONTEXT_MENU):
158 append_when_current_valid(current, menu, (p.name, boundFunction(self.runPlugin, p)), key="bullet")
159 if config.servicelist.startupservice.value == current.toString():
160 append_when_current_valid(current, menu, (_("stop using as startup service"), self.unsetStartupService), level=0)
162 append_when_current_valid(current, menu, (_("set as startup service"), self.setStartupService), level=0)
163 if self.parentalControlEnabled:
164 if self.parentalControl.getProtectionLevel(csel.getCurrentSelection().toCompareString()) == -1:
165 append_when_current_valid(current, menu, (_("add to parental protection"), boundFunction(self.addParentalProtection, current)), level=0)
167 append_when_current_valid(current, menu, (_("remove from parental protection"), boundFunction(self.removeParentalProtection, current)), level=0)
168 if config.ParentalControl.hideBlacklist.value and not parentalControl.sessionPinCached and config.ParentalControl.storeservicepin.value != "never":
169 append_when_current_valid(current, menu, (_("Unhide parental control services"), self.unhideParentalServices), level=0)
170 if SystemInfo["3DMode"] and fileExists("/usr/lib/enigma2/python/Plugins/SystemPlugins/OSD3DSetup/plugin.py"):
171 if eDVBDB.getInstance().getFlag(eServiceReference(current.toString())) & FLAG_IS_DEDICATED_3D:
172 append_when_current_valid(current, menu, (_("Unmark service as dedicated 3D service"), self.removeDedicated3DFlag), level=0)
174 append_when_current_valid(current, menu, (_("Mark service as dedicated 3D service"), self.addDedicated3DFlag), level=0)
176 bouquets = self.csel.getBouquetList()
180 bouquetCnt = len(bouquets)
181 if not self.inBouquet or bouquetCnt > 1:
182 append_when_current_valid(current, menu, (_("add service to bouquet"), self.addServiceToBouquetSelected), level=0, key="5")
183 self.addFunction = self.addServiceToBouquetSelected
184 if not self.inBouquet:
185 append_when_current_valid(current, menu, (_("remove entry"), self.removeEntry), level = 0, key="8")
186 self.removeFunction = self.removeSatelliteService
188 if not self.inBouquet:
189 append_when_current_valid(current, menu, (_("add service to favourites"), self.addServiceToBouquetSelected), level=0, key="5")
190 self.addFunction = self.addServiceToBouquetSelected
191 if SystemInfo["PIPAvailable"]:
192 if not self.parentalControlEnabled or self.parentalControl.getProtectionLevel(current.toCompareString()) == -1:
193 if self.csel.dopipzap:
194 append_when_current_valid(current, menu, (_("play in mainwindow"), self.playMain), level=0, key="red")
196 append_when_current_valid(current, menu, (_("play as picture in picture"), self.showServiceInPiP), level=0, key="blue")
197 append_when_current_valid(current, menu, (_("find currently played service"), self.findCurrentlyPlayed), level=0, key="3")
199 if 'FROM SATELLITES' in current_root.getPath() and current and _("Services") in eServiceCenter.getInstance().info(current).getName(current):
200 unsigned_orbpos = current.getUnsignedData(4) >> 16
201 if unsigned_orbpos == 0xFFFF:
202 append_when_current_valid(current, menu, (_("remove cable services"), self.removeSatelliteServices), level = 0)
203 elif unsigned_orbpos == 0xEEEE:
204 append_when_current_valid(current, menu, (_("remove terrestrial services"), self.removeSatelliteServices), level = 0)
206 append_when_current_valid(current, menu, (_("remove selected satellite"), self.removeSatelliteServices), level = 0)
208 if not self.inBouquet and not "PROVIDERS" in current_sel_path:
209 append_when_current_valid(current, menu, (_("copy to bouquets"), self.copyCurrentToBouquetList), level=0)
210 if ("flags == %d" %(FLAG_SERVICE_NEW_FOUND)) in current_sel_path:
211 append_when_current_valid(current, menu, (_("remove all new found flags"), self.removeAllNewFoundFlags), level=0)
213 append_when_current_valid(current, menu, (_("rename entry"), self.renameEntry), level=0, key="2")
214 if not inAlternativeList:
215 append_when_current_valid(current, menu, (_("remove entry"), self.removeEntry), level=0, key="8")
216 self.removeFunction = self.removeCurrentService
217 if current_root and ("flags == %d" %(FLAG_SERVICE_NEW_FOUND)) in current_root.getPath():
218 append_when_current_valid(current, menu, (_("remove new found flag"), self.removeNewFoundFlag), level=0)
220 if self.parentalControlEnabled:
221 if self.parentalControl.getProtectionLevel(current.toCompareString()) == -1:
222 append_when_current_valid(current, menu, (_("add bouquet to parental protection"), boundFunction(self.addParentalProtection, current)), level=0)
224 append_when_current_valid(current, menu, (_("remove bouquet from parental protection"), boundFunction(self.removeParentalProtection, current)), level=0)
225 menu.append(ChoiceEntryComponent(text=(_("add bouquet"), self.showBouquetInputBox)))
226 append_when_current_valid(current, menu, (_("rename entry"), self.renameEntry), level=0, key="2")
227 append_when_current_valid(current, menu, (_("remove entry"), self.removeEntry), level=0, key="8")
228 self.removeFunction = self.removeBouquet
229 if removed_userbouquets_available():
230 append_when_current_valid(current, menu, (_("purge deleted userbouquets"), self.purgeDeletedBouquets), level=0)
231 append_when_current_valid(current, menu, (_("restore deleted userbouquets"), self.restoreDeletedBouquets), level=0)
232 if self.inBouquet: # current list is editable?
233 if csel.bouquet_mark_edit == OFF:
235 append_when_current_valid(current, menu, (_("disable move mode"), self.toggleMoveMode), level=0, key="6")
237 append_when_current_valid(current, menu, (_("enable move mode"), self.toggleMoveMode), level=1, key="6")
238 if not csel.entry_marked and not inBouquetRootList and current_root and not (current_root.flags & eServiceReference.isGroup):
239 if current.type != -1:
240 menu.append(ChoiceEntryComponent(text=(_("add marker"), self.showMarkerInputBox)))
241 if not csel.movemode:
243 append_when_current_valid(current, menu, (_("enable bouquet edit"), self.bouquetMarkStart), level=0)
245 append_when_current_valid(current, menu, (_("enable favourite edit"), self.bouquetMarkStart), level=0)
246 if current_sel_flags & eServiceReference.isGroup:
247 append_when_current_valid(current, menu, (_("edit alternatives"), self.editAlternativeServices), level=2)
248 append_when_current_valid(current, menu, (_("show alternatives"), self.showAlternativeServices), level=2)
249 append_when_current_valid(current, menu, (_("remove all alternatives"), self.removeAlternativeServices), level=2)
250 elif not current_sel_flags & eServiceReference.isMarker:
251 append_when_current_valid(current, menu, (_("add alternatives"), self.addAlternativeServices), level=2)
253 if csel.bouquet_mark_edit == EDIT_BOUQUET:
255 append_when_current_valid(current, menu, (_("end bouquet edit"), self.bouquetMarkEnd), level=0)
256 append_when_current_valid(current, menu, (_("abort bouquet edit"), self.bouquetMarkAbort), level=0)
258 append_when_current_valid(current, menu, (_("end favourites edit"), self.bouquetMarkEnd), level=0)
259 append_when_current_valid(current, menu, (_("abort favourites edit"), self.bouquetMarkAbort), level=0)
260 if current_sel_flags & eServiceReference.isMarker:
261 append_when_current_valid(current, menu, (_("rename entry"), self.renameEntry), level=0, key="2")
262 append_when_current_valid(current, menu, (_("remove entry"), self.removeEntry), level=0, key="8")
263 self.removeFunction = self.removeCurrentService
265 append_when_current_valid(current, menu, (_("end alternatives edit"), self.bouquetMarkEnd), level=0)
266 append_when_current_valid(current, menu, (_("abort alternatives edit"), self.bouquetMarkAbort), level=0)
268 menu.append(ChoiceEntryComponent("menu", (_("Configuration..."), self.openSetup)))
269 self["menu"] = ChoiceList(menu)
271 def set3DMode(self, value):
272 if config.plugins.OSD3DSetup.mode.value == "auto" and self.session.nav.currentlyPlayingServiceReference == self.csel.getCurrentSelection():
273 from Plugins.SystemPlugins.OSD3DSetup.plugin import applySettings
274 applySettings(value and "sidebyside" or config.plugins.OSD3DSetup.mode.value)
276 def addDedicated3DFlag(self):
277 eDVBDB.getInstance().addFlag(eServiceReference(self.csel.getCurrentSelection().toString()), FLAG_IS_DEDICATED_3D)
278 eDVBDB.getInstance().reloadBouquets()
282 def removeDedicated3DFlag(self):
283 eDVBDB.getInstance().removeFlag(eServiceReference(self.csel.getCurrentSelection().toString()), FLAG_IS_DEDICATED_3D)
284 eDVBDB.getInstance().reloadBouquets()
285 self.set3DMode(False)
288 def isProtected(self):
289 return self.csel.protectContextMenu and config.ParentalControl.setuppinactive.value and config.ParentalControl.config_sections.context_menus.value
291 def protectResult(self, answer):
293 self.csel.protectContextMenu = False
294 elif answer is not None:
295 self.session.openWithCallback(self.close, MessageBox, _("The pin code you entered is wrong."), MessageBox.TYPE_ERROR)
299 def addServiceToBouquetOrAlternative(self):
305 def getCurrentSelectionName(self):
306 cur = self.csel.getCurrentSelection()
307 if cur and cur.valid():
308 name = eServiceCenter.getInstance().info(cur).getName(cur) or ServiceReference(cur).getServiceName() or ""
309 name = name.replace('\xc2\x86', '').replace('\xc2\x87', '')
313 def removeEntry(self):
314 if self.removeFunction and self.csel.servicelist.getCurrent() and self.csel.servicelist.getCurrent().valid():
315 if self.csel.confirmRemove:
316 list = [(_("yes"), True), (_("no"), False), (_("yes") + " " + _("and never ask again this session again"), "never")]
317 self.session.openWithCallback(self.removeFunction, MessageBox, _("Are you sure to remove this entry?") + "\n%s" % self.getCurrentSelectionName(), list=list)
319 self.removeFunction(True)
323 def removeCurrentService(self, answer):
325 if answer == "never":
326 self.csel.confirmRemove = False
327 self.csel.removeCurrentService()
330 def removeSatelliteService(self, answer):
332 if answer == "never":
333 self.csel.confirmRemove = False
334 self.csel.removeSatelliteService()
337 def removeBouquet(self, answer):
339 self.csel.removeBouquet()
340 eDVBDB.getInstance().reloadBouquets()
343 def purgeDeletedBouquets(self):
344 self.session.openWithCallback(self.purgeDeletedBouquetsCallback, MessageBox, _("Are you sure to purge all deleted userbouquets?"))
346 def purgeDeletedBouquetsCallback(self, answer):
348 for file in os.listdir("/etc/enigma2/"):
349 if file.startswith("userbouquet") and file.endswith(".del"):
350 file = "/etc/enigma2/" + file
351 print "permantly remove file ", file
355 def restoreDeletedBouquets(self):
356 for file in os.listdir("/etc/enigma2/"):
357 if file.startswith("userbouquet") and file.endswith(".del"):
358 file = "/etc/enigma2/" + file
359 print "restore file ", file[:-4]
360 os.rename(file, file[:-4])
361 eDVBDBInstance = eDVBDB.getInstance()
362 eDVBDBInstance.setLoadUnlinkedUserbouquets(True)
363 eDVBDBInstance.reloadBouquets()
364 eDVBDBInstance.setLoadUnlinkedUserbouquets(config.misc.load_unlinked_userbouquets.value)
366 self.csel.showFavourites()
370 sel = self.csel.getCurrentSelection()
371 if sel and sel.valid() and self.csel.dopipzap and (not self.parentalControlEnabled or self.parentalControl.getProtectionLevel(self.csel.getCurrentSelection().toCompareString()) == -1):
373 self.csel.setCurrentSelection(sel)
378 def okbuttonClick(self):
379 self["menu"].getCurrent()[0][1]()
382 from Screens.Setup import Setup
383 self.session.openWithCallback(self.cancelClick, Setup, "userinterface")
385 def cancelClick(self, dummy=False):
388 def showServiceInformations(self):
389 self.session.open( ServiceInfo, self.csel.getCurrentSelection() )
391 def setStartupService(self):
392 self.session.openWithCallback(self.setStartupServiceCallback, MessageBox, _("Set startup service"), list = [(_("Only on startup"), "startup"), (_("Also on standby"), "standby")])
394 def setStartupServiceCallback(self, answer):
396 config.servicelist.startupservice.value = self.csel.getCurrentSelection().toString()
397 path = ';'.join([i.toString() for i in self.csel.servicePath])
398 config.servicelist.startuproot.value = path
399 config.servicelist.startupmode.value = config.servicelist.lastmode.value
400 config.servicelist.startupservice_onstandby.value = answer == "standby"
401 config.servicelist.save()
405 def unsetStartupService(self):
406 config.servicelist.startupservice.value = ''
407 config.servicelist.startupservice_onstandby.value = False
408 config.servicelist.save()
412 def showBouquetInputBox(self):
413 self.session.openWithCallback(self.bouquetInputCallback, VirtualKeyBoard, title=_("Please enter a name for the new bouquet"), text="bouquetname", maxSize=False, visible_width=56, type=Input.TEXT)
415 def bouquetInputCallback(self, bouquet):
416 if bouquet is not None:
417 self.csel.addBouquet(bouquet, None)
420 def addParentalProtection(self, service):
421 self.parentalControl.protectService(service.toCompareString())
422 if config.ParentalControl.hideBlacklist.value and not self.parentalControl.sessionPinCached:
423 self.csel.servicelist.resetRoot()
426 def removeParentalProtection(self, service):
427 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=_("Enter pin code"))
429 def pinEntered(self, service, answer):
431 self.parentalControl.unProtectService(service)
433 elif answer is not None:
434 self.session.openWithCallback(self.close, MessageBox, _("The pin code you entered is wrong."), MessageBox.TYPE_ERROR)
438 def unhideParentalServices(self):
439 if self.csel.protectContextMenu:
440 self.session.openWithCallback(self.unhideParentalServicesCallback, PinInput, pinList=[config.ParentalControl.servicepin[0].value], triesEntry=config.ParentalControl.retries.servicepin, title=_("Enter the service pin"), windowTitle=_("Enter pin code"))
442 self.unhideParentalServicesCallback(True)
444 def unhideParentalServicesCallback(self, answer):
446 service = self.csel.servicelist.getCurrent()
447 self.parentalControl.setSessionPinCached()
448 self.parentalControl.hideBlacklist()
449 self.csel.servicelist.resetRoot()
450 self.csel.servicelist.setCurrent(service)
452 elif answer is not None:
453 self.session.openWithCallback(self.close, MessageBox, _("The pin code you entered is wrong."), MessageBox.TYPE_ERROR)
457 def showServiceInPiP(self):
458 if self.csel.dopipzap or (self.parentalControlEnabled and not self.parentalControl.getProtectionLevel(self.csel.getCurrentSelection().toCompareString()) == -1):
460 if self.session.pipshown:
462 self.session.pip = self.session.instantiateDialog(PictureInPicture)
463 self.session.pip.show()
464 newservice = self.csel.servicelist.getCurrent()
465 currentBouquet = self.csel.servicelist and self.csel.servicelist.getRoot()
466 if newservice and newservice.valid():
467 if self.session.pip.playService(newservice):
468 self.session.pipshown = True
469 self.session.pip.servicePath = self.csel.getCurrentServicePath()
470 self.session.pip.servicePath[1] = currentBouquet
473 self.session.pipshown = False
475 self.session.openWithCallback(self.close, MessageBox, _("Could not open Picture in Picture"), MessageBox.TYPE_ERROR)
479 def addServiceToBouquetSelected(self):
480 bouquets = self.csel.getBouquetList()
485 if cnt > 1: # show bouquet list
486 self.bsel = self.session.openWithCallback(self.bouquetSelClosed, BouquetSelector, bouquets, self.addCurrentServiceToBouquet)
487 elif cnt == 1: # add to only one existing bouquet
488 self.addCurrentServiceToBouquet(bouquets[0][1], closeBouquetSelection=False)
490 def bouquetSelClosed(self, recursive):
495 def removeSatelliteServices(self):
496 self.csel.removeSatelliteServices()
499 def copyCurrentToBouquetList(self):
500 self.csel.copyCurrentToBouquetList()
503 def showMarkerInputBox(self):
504 self.session.openWithCallback(self.markerInputCallback, VirtualKeyBoard, title=_("Please enter a name for the new marker"), text="markername", maxSize=False, visible_width=56, type=Input.TEXT)
506 def markerInputCallback(self, marker):
507 if marker is not None:
508 self.csel.addMarker(marker)
511 def addCurrentServiceToBouquet(self, dest, closeBouquetSelection=True):
512 self.csel.addServiceToBouquet(dest)
513 if self.bsel is not None:
514 self.bsel.close(True)
516 self.close(closeBouquetSelection) # close bouquet selection
518 def renameEntry(self):
519 if self.inBouquet and self.csel.servicelist.getCurrent() and self.csel.servicelist.getCurrent().valid() and not self.csel.entry_marked:
520 self.csel.renameEntry()
525 def toggleMoveMode(self):
526 if self.inBouquet and self.csel.servicelist.getCurrent() and self.csel.servicelist.getCurrent().valid():
527 self.csel.toggleMoveMode()
532 def toggleMoveModeSelect(self):
533 if self.inBouquet and self.csel.servicelist.getCurrent() and self.csel.servicelist.getCurrent().valid():
534 self.csel.toggleMoveMode(True)
539 def bouquetMarkStart(self):
540 self.csel.startMarkedEdit(EDIT_BOUQUET)
543 def bouquetMarkEnd(self):
544 self.csel.endMarkedEdit(abort=False)
547 def bouquetMarkAbort(self):
548 self.csel.endMarkedEdit(abort=True)
551 def removeNewFoundFlag(self):
552 eDVBDB.getInstance().removeFlag(self.csel.getCurrentSelection(), FLAG_SERVICE_NEW_FOUND)
555 def removeAllNewFoundFlags(self):
556 curpath = self.csel.getCurrentSelection().getPath()
557 idx = curpath.find("satellitePosition == ")
559 tmp = curpath[idx+21:]
562 satpos = int(tmp[:idx])
563 eDVBDB.getInstance().removeFlags(FLAG_SERVICE_NEW_FOUND, -1, -1, -1, satpos)
566 def editAlternativeServices(self):
567 self.csel.startMarkedEdit(EDIT_ALTERNATIVES)
570 def showAlternativeServices(self):
571 self.csel["Service"].editmode = True
572 self.csel.enterPath(self.csel.getCurrentSelection())
575 def removeAlternativeServices(self):
576 self.csel.removeAlternativeServices()
579 def addAlternativeServices(self):
580 self.csel.addAlternativeServices()
581 self.csel.startMarkedEdit(EDIT_ALTERNATIVES)
584 def findCurrentlyPlayed(self):
585 sel = self.csel.getCurrentSelection()
586 if sel and sel.valid() and not self.csel.entry_marked:
587 currentPlayingService = (hasattr(self.csel, "dopipzap") and self.csel.dopipzap) and self.session.pip.getCurrentService() or self.session.nav.getCurrentlyPlayingServiceOrGroup()
588 self.csel.servicelist.setCurrent(currentPlayingService, adjust=False)
589 if self.csel.getCurrentSelection() != currentPlayingService:
590 self.csel.setCurrentSelection(sel)
595 def runPlugin(self, plugin):
596 plugin(session=self.session, service=self.csel.getCurrentSelection())
599 class SelectionEventInfo:
601 self["Service"] = self["ServiceEvent"] = ServiceEvent()
602 self["Event"] = Event()
603 self.servicelist.connectSelChanged(self.__selectionChanged)
604 self.timer = eTimer()
605 self.timer.callback.append(self.updateEventInfo)
606 self.onShown.append(self.__selectionChanged)
608 def __selectionChanged(self):
610 self.timer.start(100, True)
612 def updateEventInfo(self):
613 cur = self.getCurrentSelection()
614 service = self["Service"]
615 service.newService(cur)
616 self["Event"].newEvent(service.event)
618 class ChannelSelectionEPG(InfoBarHotkey):
620 self.hotkeys = [("Info (EPG)", "info", "Infobar/openEventView"),
621 ("Info (EPG)" + " " + _("long"), "info_long", "Infobar/showEventInfoPlugins"),
622 ("Epg/Guide", "epg", "Plugins/Extensions/GraphMultiEPG/1"),
623 ("Epg/Guide" + " " + _("long"), "epg_long", "Infobar/showEventInfoPlugins")]
624 self["ChannelSelectEPGActions"] = hotkeyActionMap(["ChannelSelectEPGActions"], dict((x[1], self.hotkeyGlobal) for x in self.hotkeys))
625 self.eventViewEPG = self.start_bouquet = self.epg_bouquet = None
626 self.currentSavedPath = []
627 self.onExecBegin.append(self.clearLongkeyPressed)
629 def getKeyFunctions(self, key):
630 selection = eval("config.misc.hotkey." + key + ".value.split(',')")
633 function = list(function for function in getHotkeyFunctions() if function[1] == x and function[2] == "EPG")
635 selected.append(function[0])
638 def runPlugin(self, plugin):
639 Screens.InfoBar.InfoBar.instance.runPlugin(plugin)
641 def getEPGPluginList(self, getAll=False):
642 pluginlist = [(p.name, boundFunction(self.runPlugin, p), p.path) for p in plugins.getPlugins(where = PluginDescriptor.WHERE_EVENTINFO) \
643 if 'selectedevent' not in p.__call__.func_code.co_varnames] or []
644 from Components.ServiceEventTracker import InfoBarCount
645 if getAll or InfoBarCount == 1:
646 pluginlist.append((_("Show EPG for current channel..."), self.openSingleServiceEPG, "current_channel"))
647 pluginlist.append((_("Multi EPG"), self.openMultiServiceEPG, "multi_epg"))
648 pluginlist.append((_("Current event EPG"), self.openEventView, "event_epg"))
651 def showEventInfoPlugins(self):
652 pluginlist = self.getEPGPluginList()
654 self.session.openWithCallback(self.EventInfoPluginChosen, ChoiceBox, title=_("Please choose an extension..."), list = pluginlist, skin_name = "EPGExtensionsList")
656 self.openSingleServiceEPG()
658 def EventInfoPluginChosen(self, answer):
659 if answer is not None:
662 def openEventView(self):
664 self.epglist = epglist
665 ref = self.getCurrentSelection()
666 epg = eEPGCache.getInstance()
667 now_event = epg.lookupEventTime(ref, -1, 0)
669 epglist.append(now_event)
670 next_event = epg.lookupEventTime(ref, -1, 1)
672 epglist.append(next_event)
674 self.eventViewEPG = self.session.openWithCallback(self.eventViewEPGClosed, EventViewEPGSelect, epglist[0], ServiceReference(ref), self.eventViewEPGCallback, self.openSingleServiceEPG, self.openMultiServiceEPG, self.openSimilarList)
676 def eventViewEPGCallback(self, setEvent, setService, val):
677 epglist = self.epglist
680 epglist[0] = epglist[1]
684 def eventViewEPGClosed(self, ret=False):
685 self.eventViewEPG = None
689 def openMultiServiceEPG(self):
690 ref = self.getCurrentSelection()
692 self.start_bouquet = self.epg_bouquet = self.servicelist.getRoot()
693 self.savedService = ref
694 self.currentSavedPath = self.servicePath[:]
695 services = self.getServicesList(self.servicelist.getRoot())
696 self.session.openWithCallback(self.SingleMultiEPGClosed, EPGSelection, services, self.zapToService, None, bouquetChangeCB=self.changeBouquetForMultiEPG)
698 def openSingleServiceEPG(self):
699 ref = self.getCurrentSelection()
701 self.start_bouquet = self.epg_bouquet = self.servicelist.getRoot()
702 self.savedService = ref
703 self.currentSavedPath = self.servicePath[:]
704 self.session.openWithCallback(self.SingleMultiEPGClosed, EPGSelection, ref, self.zapToService, serviceChangeCB=self.changeServiceCB, bouquetChangeCB=self.changeBouquetForSingleEPG)
706 def openSimilarList(self, eventid, refstr):
707 self.session.open(EPGSelection, refstr, None, eventid)
709 def getServicesList(self, root):
711 servicelist = root and eServiceCenter.getInstance().list(root)
712 if not servicelist is None:
714 service = servicelist.getNext()
715 if not service.valid():
717 if service.flags & (eServiceReference.isDirectory | eServiceReference.isMarker):
719 services.append(ServiceReference(service))
722 def SingleMultiEPGClosed(self, ret=False):
724 service = self.getCurrentSelection()
725 if self.eventViewEPG:
726 self.eventViewEPG.close(service)
727 elif service is not None:
730 if self.start_bouquet != self.epg_bouquet and len(self.currentSavedPath) > 0:
732 self.enterPath(self.bouquet_root)
733 self.epg_bouquet = self.start_bouquet
734 self.enterPath(self.epg_bouquet)
735 self.setCurrentSelection(self.savedService)
737 def changeBouquetForSingleEPG(self, direction, epg):
738 if config.usage.multibouquet.value:
739 inBouquet = self.getMutableList() is not None
740 if inBouquet and len(self.servicePath) > 1:
746 cur = self.getCurrentSelection()
748 self.epg_bouquet = self.servicelist.getRoot()
749 epg.setService(ServiceReference(self.getCurrentSelection()))
751 def changeBouquetForMultiEPG(self, direction, epg):
752 if config.usage.multibouquet.value:
753 inBouquet = self.getMutableList() is not None
754 if inBouquet and len(self.servicePath) > 1:
760 cur = self.getCurrentSelection()
762 self.epg_bouquet = self.servicelist.getRoot()
763 services = self.getServicesList(self.epg_bouquet)
764 epg.setServices(services)
766 def changeServiceCB(self, direction, epg):
767 beg = self.getCurrentSelection()
773 cur = self.getCurrentSelection()
774 if cur == beg or not (cur.flags & eServiceReference.isMarker):
776 epg.setService(ServiceReference(self.getCurrentSelection()))
778 def zapToService(self, service, preview=False, zapback=False):
779 if self.startServiceRef is None:
780 self.startServiceRef = self.session.nav.getCurrentlyPlayingServiceOrGroup()
781 if service is not None:
782 if self.servicelist.getRoot() != self.epg_bouquet:
783 self.servicelist.clearPath()
784 if self.servicelist.bouquet_root != self.epg_bouquet:
785 self.servicelist.enterPath(self.servicelist.bouquet_root)
786 self.servicelist.enterPath(self.epg_bouquet)
787 self.servicelist.setCurrent(service)
788 if not zapback or preview:
789 self.zap(enable_pipzap=True)
790 if (self.dopipzap or zapback) and not preview:
793 self.startServiceRef = None
794 self.startRoot = None
795 self.revertMode = None
797 class ChannelSelectionEdit:
799 self.entry_marked = False
800 self.bouquet_mark_edit = OFF
801 self.mutableList = None
803 self.saved_title = None
804 self.saved_root = None
805 self.current_ref = None
806 self.editMode = False
807 self.confirmRemove = True
809 class ChannelSelectionEditActionMap(ActionMap):
810 def __init__(self, csel, contexts=[ ], actions={ }, prio=0):
811 ActionMap.__init__(self, contexts, actions, prio)
814 def action(self, contexts, action):
815 if action == "cancel":
816 self.csel.handleEditCancel()
817 return 0 # fall-trough
819 return 0 # fall-trough
821 return ActionMap.action(self, contexts, action)
823 self["ChannelSelectEditActions"] = ChannelSelectionEditActionMap(self, ["ChannelSelectEditActions", "OkCancelActions"],
825 "contextMenu": self.doContext,
828 def getMutableList(self, root=eServiceReference()):
829 if not self.mutableList is None:
830 return self.mutableList
831 serviceHandler = eServiceCenter.getInstance()
834 list = root and serviceHandler.list(root)
836 return list.startEdit()
839 def buildBouquetID(self, str):
843 if (c >= 'a' and c <= 'z') or (c >= '0' and c <= '9'):
849 def renameEntry(self):
851 cur = self.getCurrentSelection()
852 if cur and cur.valid():
853 name = eServiceCenter.getInstance().info(cur).getName(cur) or ServiceReference(cur).getServiceName() or ""
854 name = name.replace('\xc2\x86', '').replace('\xc2\x87', '')
856 self.session.openWithCallback(self.renameEntryCallback, VirtualKeyBoard, title=_("Please enter new name:"), text=name)
860 def renameEntryCallback(self, name):
862 mutableList = self.getMutableList()
864 current = self.servicelist.getCurrent()
865 current.setName(name)
866 index = self.servicelist.getCurrentIndex()
867 mutableList.removeService(current, False)
868 mutableList.addService(current)
869 mutableList.moveService(current, index)
870 mutableList.flushChanges()
871 self.servicelist.addService(current, True)
872 self.servicelist.removeCurrent()
873 if not self.servicelist.atEnd():
874 self.servicelist.moveUp()
876 def addMarker(self, name):
877 current = self.servicelist.getCurrent()
878 mutableList = self.getMutableList()
881 str = '1:64:%d:0:0:0:0:0:0:0::%s'%(cnt, name)
882 ref = eServiceReference(str)
883 if current and current.valid():
884 if not mutableList.addService(ref, current):
885 self.servicelist.addService(ref, True)
886 mutableList.flushChanges()
888 elif not mutableList.addService(ref):
889 self.servicelist.addService(ref, True)
890 mutableList.flushChanges()
894 def addAlternativeServices(self):
895 cur_service = ServiceReference(self.getCurrentSelection())
896 root = self.getRoot()
897 cur_root = root and ServiceReference(root)
898 mutableBouquet = cur_root.list().startEdit()
900 name = cur_service.getServiceName()
902 if self.mode == MODE_TV:
903 str = '1:134:1:0:0:0:0:0:0:0:FROM BOUQUET \"alternatives.%s.tv\" ORDER BY bouquet'%(self.buildBouquetID(name))
905 str = '1:134:2:0:0:0:0:0:0:0:FROM BOUQUET \"alternatives.%s.radio\" ORDER BY bouquet'%(self.buildBouquetID(name))
906 new_ref = ServiceReference(str)
907 if not mutableBouquet.addService(new_ref.ref, cur_service.ref):
908 mutableBouquet.removeService(cur_service.ref)
909 mutableBouquet.flushChanges()
910 eDVBDB.getInstance().reloadBouquets()
911 mutableAlternatives = new_ref.list().startEdit()
912 if mutableAlternatives:
913 mutableAlternatives.setListName(name)
914 if mutableAlternatives.addService(cur_service.ref):
915 print "add", cur_service.ref.toString(), "to new alternatives failed"
916 mutableAlternatives.flushChanges()
917 self.servicelist.addService(new_ref.ref, True)
918 self.servicelist.removeCurrent()
920 self.servicelist.moveUp()
921 if cur_service.ref.toString() == self.lastservice.value:
922 self.saveChannel(new_ref.ref)
923 if self.startServiceRef and cur_service.ref == self.startServiceRef:
924 self.startServiceRef = new_ref.ref
926 print "get mutable list for new created alternatives failed"
928 print "add", str, "to", cur_root.getServiceName(), "failed"
930 print "bouquetlist is not editable"
932 def addBouquet(self, bName, services):
933 serviceHandler = eServiceCenter.getInstance()
934 mutableBouquetList = serviceHandler.list(self.bouquet_root).startEdit()
935 if mutableBouquetList:
936 if self.mode == MODE_TV:
938 str = '1:7:1:0:0:0:0:0:0:0:FROM BOUQUET \"userbouquet.%s.tv\" ORDER BY bouquet'%(self.buildBouquetID(bName))
940 bName += _(" (Radio)")
941 str = '1:7:2:0:0:0:0:0:0:0:FROM BOUQUET \"userbouquet.%s.radio\" ORDER BY bouquet'%(self.buildBouquetID(bName))
942 new_bouquet_ref = eServiceReference(str)
943 if not mutableBouquetList.addService(new_bouquet_ref):
944 mutableBouquetList.flushChanges()
945 eDVBDB.getInstance().reloadBouquets()
946 mutableBouquet = serviceHandler.list(new_bouquet_ref).startEdit()
948 mutableBouquet.setListName(bName)
949 if services is not None:
950 for service in services:
951 if mutableBouquet.addService(service):
952 print "add", service.toString(), "to new bouquet failed"
953 mutableBouquet.flushChanges()
955 print "get mutable list for new created bouquet failed"
956 # do some voodoo to check if current_root is equal to bouquet_root
957 cur_root = self.getRoot();
958 str1 = cur_root and cur_root.toString()
959 pos1 = str1 and str1.find("FROM BOUQUET") or -1
960 pos2 = self.bouquet_rootstr.find("FROM BOUQUET")
961 if pos1 != -1 and pos2 != -1 and str1[pos1:] == self.bouquet_rootstr[pos2:]:
962 self.servicelist.addService(new_bouquet_ref)
963 self.servicelist.resetRoot()
965 print "add", str, "to bouquets failed"
967 print "bouquetlist is not editable"
969 def copyCurrentToBouquetList(self):
970 provider = ServiceReference(self.getCurrentSelection())
971 providerName = provider.getServiceName()
972 serviceHandler = eServiceCenter.getInstance()
973 services = serviceHandler.list(provider.ref)
974 self.addBouquet(providerName, services and services.getContent('R', True))
976 def removeAlternativeServices(self):
977 cur_service = ServiceReference(self.getCurrentSelection())
979 root = self.getRoot()
980 cur_root = root and ServiceReference(root)
981 list = cur_service.list()
982 first_in_alternative = list and list.getNext()
983 if first_in_alternative:
984 edit_root = cur_root and cur_root.list().startEdit()
986 if not edit_root.addService(first_in_alternative, cur_service.ref):
987 self.servicelist.addService(first_in_alternative, True)
988 if cur_service.ref.toString() == self.lastservice.value:
989 self.saveChannel(first_in_alternative)
990 if self.startServiceRef and cur_service.ref == self.startServiceRef:
991 self.startServiceRef = first_in_alternative
993 print "couldn't add first alternative service to current root"
995 print "couldn't edit current root!!"
997 print "remove empty alternative list !!"
1000 self.servicelist.moveUp()
1002 def removeBouquet(self):
1003 refstr = self.getCurrentSelection().toString()
1004 print "removeBouquet", refstr
1005 pos = refstr.find('FROM BOUQUET "')
1007 self.removeCurrentService(bouquet=True)
1009 def removeSatelliteService(self):
1010 current = self.getCurrentSelection()
1011 eDVBDB.getInstance().removeService(current)
1012 refreshServiceList()
1013 if not self.atEnd():
1014 self.servicelist.moveUp()
1016 def removeSatelliteServices(self):
1017 current = self.getCurrentSelection()
1018 unsigned_orbpos = current.getUnsignedData(4) >> 16
1019 if unsigned_orbpos == 0xFFFF:
1020 messageText = _("Are you sure to remove all cable services?")
1021 elif unsigned_orbpos == 0xEEEE:
1022 messageText = _("Are you sure to remove all terrestrial services?")
1024 if unsigned_orbpos > 1800:
1025 unsigned_orbpos = 3600 - unsigned_orbpos
1029 messageText = _("Are you sure to remove all %d.%d%s%s services?") % (unsigned_orbpos/10, unsigned_orbpos%10, "\xc2\xb0", direction)
1030 self.session.openWithCallback(self.removeSatelliteServicesCallback, MessageBox, messageText)
1032 def removeSatelliteServicesCallback(self, answer):
1034 currentIndex = self.servicelist.getCurrentIndex()
1035 current = self.getCurrentSelection()
1036 unsigned_orbpos = current.getUnsignedData(4) >> 16
1037 if unsigned_orbpos == 0xFFFF:
1038 eDVBDB.getInstance().removeServices(int("0xFFFF0000", 16) - 0x100000000)
1039 elif unsigned_orbpos == 0xEEEE:
1040 eDVBDB.getInstance().removeServices(int("0xEEEE0000", 16) - 0x100000000)
1042 curpath = current.getPath()
1043 idx = curpath.find("satellitePosition == ")
1045 tmp = curpath[idx + 21:]
1048 satpos = int(tmp[:idx])
1049 eDVBDB.getInstance().removeServices(-1, -1, -1, satpos)
1050 refreshServiceList()
1051 if hasattr(self, 'showSatellites'):
1052 self.showSatellites()
1053 self.servicelist.moveToIndex(currentIndex)
1054 if currentIndex != self.servicelist.getCurrentIndex():
1055 self.servicelist.instance.moveSelection(self.servicelist.instance.moveEnd)
1057 # multiple marked entry stuff ( edit mode, later multiepg selection )
1058 def startMarkedEdit(self, type):
1059 self.savedPath = self.servicePath[:]
1060 if type == EDIT_ALTERNATIVES:
1061 self.current_ref = self.getCurrentSelection()
1062 self.enterPath(self.current_ref)
1063 self.mutableList = self.getMutableList()
1064 # add all services from the current list to internal marked set in listboxservicecontent
1065 self.clearMarks() # this clears the internal marked set in the listboxservicecontent
1066 self.saved_title = self.getTitle()
1067 pos = self.saved_title.find(')')
1068 new_title = self.saved_title[:pos+1]
1069 if type == EDIT_ALTERNATIVES:
1070 self.bouquet_mark_edit = EDIT_ALTERNATIVES
1071 new_title += ' ' + _("[alternative edit]")
1073 self.bouquet_mark_edit = EDIT_BOUQUET
1074 if config.usage.multibouquet.value:
1075 new_title += ' ' + _("[bouquet edit]")
1077 new_title += ' ' + _("[favourite edit]")
1078 self.setTitle(new_title)
1079 self.__marked = self.servicelist.getRootServices()
1080 for x in self.__marked:
1081 self.servicelist.addMarked(eServiceReference(x))
1082 self["Service"].editmode = True
1084 def endMarkedEdit(self, abort):
1085 if not abort and self.mutableList is not None:
1086 new_marked = set(self.servicelist.getMarked())
1087 old_marked = set(self.__marked)
1088 removed = old_marked - new_marked
1089 added = new_marked - old_marked
1093 self.mutableList.removeService(eServiceReference(x))
1096 self.mutableList.addService(eServiceReference(x))
1098 if self.bouquet_mark_edit == EDIT_ALTERNATIVES and not new_marked and self.__marked:
1099 self.mutableList.addService(eServiceReference(self.__marked[0]))
1100 self.mutableList.flushChanges()
1103 self.bouquet_mark_edit = OFF
1104 self.mutableList = None
1105 self.setTitle(self.saved_title)
1106 self.saved_title = None
1107 # self.servicePath is just a reference to servicePathTv or Radio...
1108 # so we never ever do use the asignment operator in self.servicePath
1109 del self.servicePath[:] # remove all elements
1110 self.servicePath += self.savedPath # add saved elements
1112 self.setRoot(self.servicePath[-1])
1113 if self.current_ref:
1114 self.setCurrentSelection(self.current_ref)
1115 self.current_ref = None
1117 def clearMarks(self):
1118 self.servicelist.clearMarks()
1121 ref = self.servicelist.getCurrent()
1122 if self.servicelist.isMarked(ref):
1123 self.servicelist.removeMarked(ref)
1125 self.servicelist.addMarked(ref)
1127 def removeCurrentEntry(self, bouquet=False):
1128 if self.confirmRemove:
1129 list = [(_("yes"), True), (_("no"), False), (_("yes") + " " + _("and never ask again this session again"), "never")]
1130 self.session.openWithCallback(boundFunction(self.removeCurrentEntryCallback, bouquet), MessageBox, _("Are you sure to remove this entry?"), list=list)
1132 self.removeCurrentEntryCallback(bouquet, True)
1134 def removeCurrentEntryCallback(self, bouquet, answer):
1136 if answer == "never":
1137 self.confirmRemove = False
1139 self.removeBouquet()
1141 self.removeCurrentService()
1143 def removeCurrentService(self, bouquet=False):
1144 self.editMode = True
1145 ref = self.servicelist.getCurrent()
1146 mutableList = self.getMutableList()
1147 if ref.valid() and mutableList is not None:
1148 if not mutableList.removeService(ref):
1149 mutableList.flushChanges() #FIXME dont flush on each single removed service
1150 self.servicelist.removeCurrent()
1151 self.servicelist.resetRoot()
1152 playingref = self.session.nav.getCurrentlyPlayingServiceOrGroup()
1153 if not bouquet and playingref and ref == playingref:
1154 self.channelSelected(doClose=False)
1156 def addServiceToBouquet(self, dest, service=None):
1157 mutableList = self.getMutableList(dest)
1158 if not mutableList is None:
1159 if service is None: #use current selected service
1160 service = self.servicelist.getCurrent()
1161 if not mutableList.addService(service):
1162 mutableList.flushChanges()
1163 # do some voodoo to check if current_root is equal to dest
1164 cur_root = self.getRoot();
1165 str1 = cur_root and cur_root.toString() or -1
1166 str2 = dest.toString()
1167 pos1 = str1.find("FROM BOUQUET")
1168 pos2 = str2.find("FROM BOUQUET")
1169 if pos1 != -1 and pos2 != -1 and str1[pos1:] == str2[pos2:]:
1170 self.servicelist.addService(service)
1171 self.servicelist.resetRoot()
1173 def toggleMoveMode(self, select=False):
1174 self.editMode = True
1176 if self.entry_marked:
1177 self.toggleMoveMarked() # unmark current entry
1178 self.movemode = False
1179 self.mutableList.flushChanges() # FIXME add check if changes was made
1180 self.mutableList = None
1181 self.setTitle(self.saved_title)
1182 self.saved_title = None
1183 self.servicelist.resetRoot()
1184 self.servicelist.l.setHideNumberMarker(config.usage.hide_number_markers.value)
1185 self.servicelist.setCurrent(self.servicelist.getCurrent())
1187 self.mutableList = self.getMutableList()
1188 self.movemode = True
1189 select and self.toggleMoveMarked()
1190 self.saved_title = self.getTitle()
1191 pos = self.saved_title.find(')')
1192 self.setTitle(self.saved_title[:pos+1] + ' ' + _("[move mode]") + self.saved_title[pos+1:]);
1193 self.servicelist.l.setHideNumberMarker(False)
1194 self.servicelist.setCurrent(self.servicelist.getCurrent())
1195 self["Service"].editmode = True
1197 def handleEditCancel(self):
1198 if self.movemode: #movemode active?
1199 self.toggleMoveMode() # disable move mode
1200 elif self.bouquet_mark_edit != OFF:
1201 self.endMarkedEdit(True) # abort edit mode
1203 def toggleMoveMarked(self):
1204 if self.entry_marked:
1205 self.servicelist.setCurrentMarked(False)
1206 self.entry_marked = False
1207 self.pathChangeDisabled = False # re-enable path change
1209 self.servicelist.setCurrentMarked(True)
1210 self.entry_marked = True
1211 self.pathChangeDisabled = True # no path change allowed in movemod
1213 def doContext(self):
1214 self.session.openWithCallback(self.exitContext, ChannelContextMenu, self)
1216 def exitContext(self, close=False):
1223 # type 1 = digital television service
1224 # type 4 = nvod reference service (NYI)
1225 # type 17 = MPEG-2 HD digital television service
1226 # type 22 = advanced codec SD digital television
1227 # type 24 = advanced codec SD NVOD reference service (NYI)
1228 # type 25 = advanced codec HD digital television
1229 # type 27 = advanced codec HD NVOD reference service (NYI)
1230 # type 2 = digital radio sound service
1231 # type 10 = advanced codec digital radio sound service
1233 service_types_tv = '1:7:1:0:0:0:0:0:0:0:(type == 1) || (type == 17) || (type == 22) || (type == 25) || (type == 134) || (type == 195)'
1234 service_types_radio = '1:7:2:0:0:0:0:0:0:0:(type == 2) || (type == 10)'
1236 class ChannelSelectionBase(Screen):
1237 def __init__(self, session):
1238 Screen.__init__(self, session)
1240 self["key_red"] = Button(_("All"))
1241 self["key_green"] = Button(_("Satellites"))
1242 self["key_yellow"] = Button(_("Provider"))
1243 self["key_blue"] = Button(_("Favourites"))
1245 self["list"] = ServiceList(self)
1246 self.servicelist = self["list"]
1248 self.numericalTextInput = NumericalTextInput(handleTimeout=False)
1249 self.numericalTextInput.setUseableChars(u'1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ')
1251 self.servicePathTV = [ ]
1252 self.servicePathRadio = [ ]
1253 self.servicePath = [ ]
1255 self.rootChanged = False
1256 self.startRoot = None
1257 self.selectionNumber = ""
1258 self.clearNumberSelectionNumberTimer = eTimer()
1259 self.clearNumberSelectionNumberTimer.callback.append(self.clearNumberSelectionNumber)
1260 self.protectContextMenu = True
1263 self.dopipzap = False
1264 self.pathChangeDisabled = False
1265 self.movemode = False
1266 self.showSatDetails = False
1268 self["ChannelSelectBaseActions"] = NumberActionMap(["ChannelSelectBaseActions", "NumberActions", "InputAsciiActions"],
1270 "showFavourites": self.showFavourites,
1271 "showAllServices": self.showAllServices,
1272 "showProviders": self.showProviders,
1273 "showSatellites": boundFunction(self.showSatellites, changeMode=True),
1274 "nextBouquet": self.nextBouquet,
1275 "prevBouquet": self.prevBouquet,
1276 "nextMarker": self.nextMarker,
1277 "prevMarker": self.prevMarker,
1278 "gotAsciiCode": self.keyAsciiCode,
1279 "keyLeft": self.keyLeft,
1280 "keyRight": self.keyRight,
1281 "keyRecord": self.keyRecord,
1282 "1": self.keyNumberGlobal,
1283 "2": self.keyNumberGlobal,
1284 "3": self.keyNumberGlobal,
1285 "4": self.keyNumberGlobal,
1286 "5": self.keyNumberGlobal,
1287 "6": self.keyNumberGlobal,
1288 "7": self.keyNumberGlobal,
1289 "8": self.keyNumberGlobal,
1290 "9": self.keyNumberGlobal,
1291 "0": self.keyNumber0
1293 self.maintitle = _("Channel selection")
1294 self.recallBouquetMode()
1296 def getBouquetNumOffset(self, bouquet):
1297 if not config.usage.multibouquet.value:
1299 str = bouquet.toString()
1301 if 'userbouquet.' in bouquet.toCompareString():
1302 serviceHandler = eServiceCenter.getInstance()
1303 servicelist = serviceHandler.list(bouquet)
1304 if not servicelist is None:
1306 serviceIterator = servicelist.getNext()
1307 if not serviceIterator.valid(): #check if end of list
1309 number = serviceIterator.getChannelNum()
1315 def recallBouquetMode(self):
1316 if self.mode == MODE_TV:
1317 self.service_types = service_types_tv
1318 if config.usage.multibouquet.value:
1319 self.bouquet_rootstr = '1:7:1:0:0:0:0:0:0:0:FROM BOUQUET "bouquets.tv" ORDER BY bouquet'
1321 self.bouquet_rootstr = '%s FROM BOUQUET "userbouquet.favourites.tv" ORDER BY bouquet'%(self.service_types)
1323 self.service_types = service_types_radio
1324 if config.usage.multibouquet.value:
1325 self.bouquet_rootstr = '1:7:1:0:0:0:0:0:0:0:FROM BOUQUET "bouquets.radio" ORDER BY bouquet'
1327 self.bouquet_rootstr = '%s FROM BOUQUET "userbouquet.favourites.radio" ORDER BY bouquet'%(self.service_types)
1328 self.bouquet_root = eServiceReference(self.bouquet_rootstr)
1330 def setTvMode(self):
1332 self.servicePath = self.servicePathTV
1333 self.recallBouquetMode()
1334 title = self.maintitle
1335 pos = title.find(" (")
1339 self.setTitle(title)
1341 def setRadioMode(self):
1342 self.mode = MODE_RADIO
1343 self.servicePath = self.servicePathRadio
1344 self.recallBouquetMode()
1345 title = self.maintitle
1346 pos = title.find(" (")
1349 title += _(" (Radio)")
1350 self.setTitle(title)
1352 def setRoot(self, root, justSet=False):
1353 if self.startRoot is None:
1354 self.startRoot = self.getRoot()
1355 path = root.getPath()
1356 isBouquet = 'FROM BOUQUET' in path and (root.flags & eServiceReference.isDirectory)
1357 inBouquetRootList = 'FROM BOUQUET "bouquets.' in path #FIXME HACK
1358 if not inBouquetRootList and isBouquet:
1359 self.servicelist.setMode(ServiceList.MODE_FAVOURITES)
1361 self.servicelist.setMode(ServiceList.MODE_NORMAL)
1362 self.servicelist.setRoot(root, justSet)
1363 self.rootChanged = True
1364 self.buildTitleString()
1366 def removeModeStr(self, str):
1367 if self.mode == MODE_TV:
1368 pos = str.find(_(" (TV)"))
1370 pos = str.find(_(" (Radio)"))
1375 def getServiceName(self, ref):
1376 str = self.removeModeStr(ServiceReference(ref).getServiceName())
1377 if 'User - bouquets' in str:
1378 return _("User - bouquets")
1380 pathstr = ref.getPath()
1381 if 'FROM PROVIDERS' in pathstr:
1382 return _("Provider")
1383 if 'FROM SATELLITES' in pathstr:
1384 return _("Satellites")
1385 if ') ORDER BY name' in pathstr:
1389 def buildTitleString(self):
1390 titleStr = self.getTitle()
1391 pos = titleStr.find(']')
1393 pos = titleStr.find(')')
1395 titleStr = titleStr[:pos+1]
1396 Len = len(self.servicePath)
1398 base_ref = self.servicePath[0]
1400 end_ref = self.servicePath[Len-1]
1403 nameStr = self.getServiceName(base_ref)
1404 titleStr += ' - ' + nameStr
1405 if end_ref is not None:
1410 nameStr = self.getServiceName(end_ref)
1412 self.setTitle(titleStr)
1415 self.servicelist.moveUp()
1418 self.servicelist.moveDown()
1420 def clearPath(self):
1421 del self.servicePath[:]
1423 def enterPath(self, ref, justSet=False):
1424 self.servicePath.append(ref)
1425 self.setRoot(ref, justSet)
1427 def enterUserbouquet(self, root, save_root=True):
1429 self.recallBouquetMode()
1430 if self.bouquet_root:
1431 self.enterPath(self.bouquet_root)
1432 self.enterPath(root)
1433 self.startRoot = None
1437 def pathUp(self, justSet=False):
1438 prev = self.servicePath.pop()
1439 if self.servicePath:
1440 current = self.servicePath[-1]
1441 self.setRoot(current, justSet)
1443 self.setCurrentSelection(prev)
1446 def isBasePathEqual(self, ref):
1447 if len(self.servicePath) > 1 and self.servicePath[0] == ref:
1451 def isPrevPathEqual(self, ref):
1452 length = len(self.servicePath)
1453 if length > 1 and self.servicePath[length-2] == ref:
1457 def preEnterPath(self, refstr):
1460 def showAllServices(self):
1461 if not self.pathChangeDisabled:
1462 refstr = '%s ORDER BY name'%(self.service_types)
1463 if not self.preEnterPath(refstr):
1464 ref = eServiceReference(refstr)
1465 currentRoot = self.getRoot()
1466 if currentRoot is None or currentRoot != ref:
1469 playingref = self.session.nav.getCurrentlyPlayingServiceOrGroup()
1471 self.setCurrentSelectionAlternative(playingref)
1473 def showSatellites(self, changeMode=False):
1474 if not self.pathChangeDisabled:
1475 refstr = '%s FROM SATELLITES ORDER BY satellitePosition'%(self.service_types)
1476 if not self.preEnterPath(refstr):
1477 ref = eServiceReference(refstr)
1481 if self.isBasePathEqual(ref):
1482 if self.isPrevPathEqual(ref):
1484 prev = self.pathUp(justSet)
1486 currentRoot = self.getRoot()
1487 if currentRoot is None or currentRoot != ref:
1490 self.enterPath(ref, True)
1491 if changeMode and currentRoot and currentRoot == ref:
1492 self.showSatDetails = not self.showSatDetails
1495 self.enterPath(ref, True)
1497 addCableAndTerrestrialLater = []
1498 serviceHandler = eServiceCenter.getInstance()
1499 servicelist = serviceHandler.list(ref)
1500 if not servicelist is None:
1502 service = servicelist.getNext()
1503 if not service.valid(): #check if end of list
1505 unsigned_orbpos = service.getUnsignedData(4) >> 16
1506 orbpos = service.getData(4) >> 16
1509 if "FROM PROVIDER" in service.getPath():
1510 service_type = self.showSatDetails and _("Providers")
1511 elif ("flags == %d" %(FLAG_SERVICE_NEW_FOUND)) in service.getPath():
1512 service_type = self.showSatDetails and _("New")
1514 service_type = _("Services")
1516 if unsigned_orbpos == 0xFFFF: #Cable
1517 service_name = _("Cable")
1518 addCableAndTerrestrialLater.append(("%s - %s" % (service_name, service_type), service.toString()))
1519 elif unsigned_orbpos == 0xEEEE: #Terrestrial
1520 service_name = _("Terrestrial")
1521 addCableAndTerrestrialLater.append(("%s - %s" % (service_name, service_type), service.toString()))
1524 service_name = str(nimmanager.getSatDescription(orbpos))
1526 if orbpos > 1800: # west
1527 orbpos = 3600 - orbpos
1531 service_name = ("%d.%d" + h) % (orbpos / 10, orbpos % 10)
1532 service.setName("%s - %s" % (service_name, service_type))
1533 self.servicelist.addService(service)
1534 cur_ref = self.session.nav.getCurrentlyPlayingServiceReference()
1535 self.servicelist.l.sort()
1537 pos = self.service_types.rfind(':')
1538 refstr = '%s (channelID == %08x%04x%04x) && %s ORDER BY name' %(self.service_types[:pos+1],
1539 cur_ref.getUnsignedData(4), # NAMESPACE
1540 cur_ref.getUnsignedData(2), # TSID
1541 cur_ref.getUnsignedData(3), # ONID
1542 self.service_types[pos+1:])
1543 ref = eServiceReference(refstr)
1544 ref.setName(_("Current transponder"))
1545 self.servicelist.addService(ref, beforeCurrent=True)
1546 for (service_name, service_ref) in addCableAndTerrestrialLater:
1547 ref = eServiceReference(service_ref)
1548 ref.setName(service_name)
1549 self.servicelist.addService(ref, beforeCurrent=True)
1550 self.servicelist.l.FillFinished()
1551 if prev is not None:
1552 self.setCurrentSelection(prev)
1554 refstr = cur_ref.toString()
1555 op = "".join(refstr.split(':', 10)[6:7])
1557 hop = int(op[:-4],16)
1558 if len(op) >= 7 and not op.endswith('0000'):
1559 op = op[:-4] + '0000'
1560 refstr = '1:7:0:0:0:0:%s:0:0:0:(satellitePosition == %s) && %s ORDER BY name' % (op, hop, self.service_types[self.service_types.rfind(':')+1:])
1561 self.setCurrentSelectionAlternative(eServiceReference(refstr))
1563 def showProviders(self):
1564 if not self.pathChangeDisabled:
1565 refstr = '%s FROM PROVIDERS ORDER BY name'%(self.service_types)
1566 if not self.preEnterPath(refstr):
1567 ref = eServiceReference(refstr)
1568 if self.isBasePathEqual(ref):
1571 currentRoot = self.getRoot()
1572 if currentRoot is None or currentRoot != ref:
1575 service = self.session.nav.getCurrentService()
1577 info = service.info()
1579 provider = info.getInfoString(iServiceInformation.sProvider)
1580 refstr = '1:7:0:0:0:0:0:0:0:0:(provider == \"%s\") && %s ORDER BY name:%s' % (provider, self.service_types[self.service_types.rfind(':')+1:],provider)
1581 self.setCurrentSelectionAlternative(eServiceReference(refstr))
1583 def changeBouquet(self, direction):
1584 if not self.pathChangeDisabled:
1585 if len(self.servicePath) > 1:
1586 #when enter satellite root list we must do some magic stuff..
1587 ref = eServiceReference('%s FROM SATELLITES ORDER BY satellitePosition'%(self.service_types))
1588 if self.isBasePathEqual(ref):
1589 self.showSatellites()
1596 ref = self.getCurrentSelection()
1599 def inBouquet(self):
1600 if self.servicePath and self.servicePath[0] == self.bouquet_root:
1605 return self.servicelist.atBegin()
1608 return self.servicelist.atEnd()
1610 def nextBouquet(self):
1611 if self.shown and config.usage.oldstyle_channel_select_controls.value:
1612 self.servicelist.instance.moveSelection(self.servicelist.instance.pageUp)
1613 elif "reverseB" in config.usage.servicelist_cursor_behavior.value:
1614 self.changeBouquet(-1)
1616 self.changeBouquet(+1)
1618 def prevBouquet(self):
1619 if self.shown and config.usage.oldstyle_channel_select_controls.value:
1620 self.servicelist.instance.moveSelection(self.servicelist.instance.pageDown)
1621 elif "reverseB" in config.usage.servicelist_cursor_behavior.value:
1622 self.changeBouquet(+1)
1624 self.changeBouquet(-1)
1627 if config.usage.oldstyle_channel_select_controls.value:
1628 self.changeBouquet(-1)
1630 self.servicelist.instance.moveSelection(self.servicelist.instance.pageUp)
1633 if config.usage.oldstyle_channel_select_controls.value:
1634 self.changeBouquet(+1)
1636 self.servicelist.instance.moveSelection(self.servicelist.instance.pageDown)
1638 def keyRecord(self):
1639 ref = self.getCurrentSelection()
1640 if ref and not(ref.flags & (eServiceReference.isMarker|eServiceReference.isDirectory)):
1641 Screens.InfoBar.InfoBar.instance.instantRecord(serviceRef=ref)
1643 def showFavourites(self):
1644 if not self.pathChangeDisabled:
1645 if not self.preEnterPath(self.bouquet_rootstr):
1646 if self.isBasePathEqual(self.bouquet_root):
1649 currentRoot = self.getRoot()
1650 if currentRoot is None or currentRoot != self.bouquet_root:
1652 self.enterPath(self.bouquet_root)
1654 def keyNumber0(self, number):
1655 if len(self.servicePath) > 1 and not self.selectionNumber:
1658 self.keyNumberGlobal(number)
1660 def keyNumberGlobal(self, number):
1661 if self.isBasePathEqual(self.bouquet_root):
1662 if hasattr(self, "editMode") and self.editMode:
1666 self.toggleMoveMode(select=True)
1668 self.removeCurrentEntry(bouquet=False)
1670 self.numberSelectionActions(number)
1672 current_root = self.getRoot()
1673 if current_root and 'FROM BOUQUET "bouquets.' in current_root.getPath():
1674 if hasattr(self, "editMode") and self.editMode:
1678 self.toggleMoveMode(select=True)
1680 self.removeCurrentEntry(bouquet=True)
1682 self.numberSelectionActions(number)
1684 unichar = self.numericalTextInput.getKey(number)
1685 charstr = unichar.encode("utf-8")
1686 if len(charstr) == 1:
1687 self.servicelist.moveToChar(charstr[0])
1689 def numberSelectionActions(self, number):
1690 if not(hasattr(self, "movemode") and self.movemode):
1691 if len(self.selectionNumber)>4:
1692 self.clearNumberSelectionNumber()
1693 self.selectionNumber = self.selectionNumber + str(number)
1694 ref, bouquet = Screens.InfoBar.InfoBar.instance.searchNumber(int(self.selectionNumber), bouquet=self.getRoot())
1696 if not ref.flags & eServiceReference.isMarker:
1697 self.enterUserbouquet(bouquet, save_root=False)
1698 self.servicelist.setCurrent(ref)
1699 self.clearNumberSelectionNumberTimer.start(1000, True)
1701 self.clearNumberSelectionNumber()
1703 def clearNumberSelectionNumber(self):
1704 self.clearNumberSelectionNumberTimer.stop()
1705 self.selectionNumber = ""
1707 def keyAsciiCode(self):
1708 unichar = unichr(getPrevAsciiCode())
1709 charstr = unichar.encode("utf-8")
1710 if len(charstr) == 1:
1711 self.servicelist.moveToChar(charstr[0])
1714 return self.servicelist.getRoot()
1716 def getCurrentSelection(self):
1717 return self.servicelist.getCurrent()
1719 def setCurrentSelection(self, service):
1721 self.servicelist.setCurrent(service, adjust=False)
1723 def setCurrentSelectionAlternative(self, ref):
1724 if self.bouquet_mark_edit == EDIT_ALTERNATIVES and not (ref.flags & eServiceReference.isDirectory):
1725 for markedService in self.servicelist.getMarked():
1726 markedService = eServiceReference(markedService)
1727 self.setCurrentSelection(markedService)
1728 if markedService == self.getCurrentSelection():
1730 self.setCurrentSelection(ref)
1732 def getBouquetList(self):
1734 serviceHandler = eServiceCenter.getInstance()
1735 if config.usage.multibouquet.value:
1736 list = serviceHandler.list(self.bouquet_root)
1742 if s.flags & eServiceReference.isDirectory and not s.flags & eServiceReference.isInvisible:
1743 info = serviceHandler.info(s)
1745 bouquets.append((info.getName(s), s))
1748 info = serviceHandler.info(self.bouquet_root)
1750 bouquets.append((info.getName(self.bouquet_root), self.bouquet_root))
1755 if len(self.servicePath) > 1:
1756 if self.isBasePathEqual(self.bouquet_root):
1757 self.showFavourites()
1759 ref = eServiceReference('%s FROM SATELLITES ORDER BY satellitePosition'%(self.service_types))
1760 if self.isBasePathEqual(ref):
1761 self.showSatellites()
1763 ref = eServiceReference('%s FROM PROVIDERS ORDER BY name'%(self.service_types))
1764 if self.isBasePathEqual(ref):
1765 self.showProviders()
1767 self.showAllServices()
1769 def nextMarker(self):
1770 self.servicelist.moveToNextMarker()
1772 def prevMarker(self):
1773 self.servicelist.moveToPrevMarker()
1775 def gotoCurrentServiceOrProvider(self, ref):
1776 str = ref.toString()
1777 if _("Providers") in str:
1778 service = self.session.nav.getCurrentService()
1780 info = service.info()
1782 provider = info.getInfoString(iServiceInformation.sProvider)
1783 op = int(self.session.nav.getCurrentlyPlayingServiceOrGroup().toString().split(':')[6][:-4] or "0",16)
1784 refstr = '1:7:0:0:0:0:0:0:0:0:(provider == \"%s\") && (satellitePosition == %s) && %s ORDER BY name:%s' % (provider, op, self.service_types[self.service_types.rfind(':')+1:],provider)
1785 self.servicelist.setCurrent(eServiceReference(refstr))
1786 elif not self.isBasePathEqual(self.bouquet_root) or self.bouquet_mark_edit == EDIT_ALTERNATIVES:
1787 playingref = self.session.nav.getCurrentlyPlayingServiceOrGroup()
1789 self.setCurrentSelectionAlternative(playingref)
1793 #config for lastservice
1794 config.tv = ConfigSubsection()
1795 config.tv.lastservice = ConfigText()
1796 config.tv.lastroot = ConfigText()
1797 config.radio = ConfigSubsection()
1798 config.radio.lastservice = ConfigText()
1799 config.radio.lastroot = ConfigText()
1800 config.servicelist = ConfigSubsection()
1801 config.servicelist.lastmode = ConfigText(default = "tv")
1802 config.servicelist.startupservice = ConfigText()
1803 config.servicelist.startupservice_onstandby = ConfigYesNo(default = False)
1804 config.servicelist.startuproot = ConfigText()
1805 config.servicelist.startupmode = ConfigText(default = "tv")
1807 class ChannelSelection(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelectionEPG, SelectionEventInfo):
1808 def __init__(self, session):
1809 ChannelSelectionBase.__init__(self,session)
1810 ChannelSelectionEdit.__init__(self)
1811 ChannelSelectionEPG.__init__(self)
1812 SelectionEventInfo.__init__(self)
1814 self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"],
1816 "cancel": self.cancel,
1817 "ok": self.channelSelected,
1818 "keyRadio": self.doRadioButton,
1819 "keyTV": self.doTVButton,
1822 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
1824 iPlayableService.evStart: self.__evServiceStart,
1825 iPlayableService.evEnd: self.__evServiceEnd
1828 self.startServiceRef = None
1831 self.history_pos = 0
1833 if config.servicelist.startupservice.value and config.servicelist.startuproot.value:
1834 config.servicelist.lastmode.value = config.servicelist.startupmode.value
1835 if config.servicelist.lastmode.value == "tv":
1836 config.tv.lastservice.value = config.servicelist.startupservice.value
1837 config.tv.lastroot.value = config.servicelist.startuproot.value
1838 elif config.servicelist.lastmode.value == "radio":
1839 config.radio.lastservice.value = config.servicelist.startupservice.value
1840 config.radio.lastroot.value = config.servicelist.startuproot.value
1842 self.lastservice = config.tv.lastservice
1843 self.lastroot = config.tv.lastroot
1844 self.revertMode = None
1845 config.usage.multibouquet.addNotifier(self.multibouquet_config_changed)
1846 self.new_service_played = False
1847 self.dopipzap = False
1848 self.onExecBegin.append(self.asciiOn)
1849 self.mainScreenMode = None
1850 self.mainScreenRoot = None
1852 self.lastChannelRootTimer = eTimer()
1853 self.lastChannelRootTimer.callback.append(self.__onCreate)
1854 self.lastChannelRootTimer.start(100,True)
1855 self.pipzaptimer = eTimer()
1858 rcinput = eRCInput.getInstance()
1859 rcinput.setKeyboardMode(rcinput.kmAscii)
1862 rcinput = eRCInput.getInstance()
1863 rcinput.setKeyboardMode(rcinput.kmNone)
1865 def multibouquet_config_changed(self, val):
1866 self.recallBouquetMode()
1868 def __evServiceStart(self):
1869 if self.dopipzap and hasattr(self.session, 'pip'):
1870 self.servicelist.setPlayableIgnoreService(self.session.pip.getCurrentServiceReference() or eServiceReference())
1872 service = self.session.nav.getCurrentService()
1874 info = service.info()
1876 refstr = info.getInfoString(iServiceInformation.sServiceref)
1877 self.servicelist.setPlayableIgnoreService(eServiceReference(refstr))
1879 def __evServiceEnd(self):
1880 self.servicelist.setPlayableIgnoreService(eServiceReference())
1883 self.rootChanged = True
1885 lastservice = eServiceReference(self.lastservice.value)
1886 if lastservice.valid():
1887 self.setCurrentSelection(lastservice)
1889 def doTVButton(self):
1890 if self.mode == MODE_TV:
1891 self.channelSelected(doClose = False)
1895 def setModeTv(self):
1896 if self.revertMode is None:
1897 self.revertMode = self.mode
1898 self.lastservice = config.tv.lastservice
1899 self.lastroot = config.tv.lastroot
1900 config.servicelist.lastmode.value = "tv"
1904 def doRadioButton(self):
1905 if self.mode == MODE_RADIO:
1906 self.channelSelected(doClose=False)
1910 def setModeRadio(self):
1911 if self.revertMode is None:
1912 self.revertMode = self.mode
1913 if config.usage.e1like_radio_mode.value:
1914 self.lastservice = config.radio.lastservice
1915 self.lastroot = config.radio.lastroot
1916 config.servicelist.lastmode.value = "radio"
1920 def __onCreate(self):
1921 if config.usage.e1like_radio_mode.value:
1922 if config.servicelist.lastmode.value == "tv":
1928 lastservice = eServiceReference(self.lastservice.value)
1929 if lastservice.valid():
1932 def channelSelected(self, doClose = True):
1933 playingref = self.session.nav.getCurrentlyPlayingServiceOrGroup()
1934 if config.usage.channelselection_preview.value and (playingref is None or self.getCurrentSelection() and self.getCurrentSelection() != playingref):
1936 if not self.startServiceRef and not doClose:
1937 self.startServiceRef = playingref
1938 ref = self.getCurrentSelection()
1939 if self.movemode and (self.isBasePathEqual(self.bouquet_root) or "userbouquet." in ref.toString()):
1940 self.toggleMoveMarked()
1941 elif (ref.flags & eServiceReference.flagDirectory) == eServiceReference.flagDirectory:
1942 if Components.ParentalControl.parentalControl.isServicePlayable(ref, self.bouquetParentalControlCallback, self.session):
1944 self.gotoCurrentServiceOrProvider(ref)
1945 elif self.bouquet_mark_edit != OFF:
1946 if not (self.bouquet_mark_edit == EDIT_ALTERNATIVES and ref.flags & eServiceReference.isGroup):
1948 elif not (ref.flags & eServiceReference.isMarker or ref.type == -1):
1949 root = self.getRoot()
1950 if not root or not (root.flags & eServiceReference.isGroup):
1951 self.zap(enable_pipzap=doClose, preview_zap=not doClose)
1956 self.startServiceRef = None
1957 self.startRoot = None
1958 self.correctChannelNumber()
1959 self.movemode and self.toggleMoveMode()
1960 self.editMode = False
1961 self.protectContextMenu = True
1964 def bouquetParentalControlCallback(self, ref):
1966 self.gotoCurrentServiceOrProvider(ref)
1968 def togglePipzap(self):
1969 assert(self.session.pip)
1970 title = self.instance.getTitle()
1971 pos = title.find(" (")
1975 # Mark PiP as inactive and effectively deactivate pipzap
1976 self.hidePipzapMessage()
1977 self.dopipzap = False
1979 # Disable PiP if not playing a service
1980 if self.session.pip.pipservice is None:
1981 self.session.pipshown = False
1982 del self.session.pip
1983 self.__evServiceStart()
1984 # Move to playing service
1985 lastservice = eServiceReference(self.lastservice.value)
1986 if lastservice.valid() and self.getCurrentSelection() != lastservice:
1987 self.setCurrentSelection(lastservice)
1991 # Mark PiP as active and effectively active pipzap
1992 self.showPipzapMessage()
1993 self.dopipzap = True
1994 self.__evServiceStart()
1995 # Move to service playing in pip (will not work with subservices)
1996 self.setCurrentSelection(self.session.pip.getCurrentService())
1998 title += _(" (PiP)")
1999 self.setTitle(title)
2000 self.buildTitleString()
2002 def showPipzapMessage(self):
2003 time = config.usage.infobar_timeout.index
2005 self.pipzaptimer.callback.append(self.hidePipzapMessage)
2006 self.pipzaptimer.startLongTimer(time)
2007 self.session.pip.active()
2009 def hidePipzapMessage(self):
2010 if self.pipzaptimer.isActive():
2011 self.pipzaptimer.callback.remove(self.hidePipzapMessage)
2012 self.pipzaptimer.stop()
2013 self.session.pip.inactive()
2015 #called from infoBar and channelSelected
2016 def zap(self, enable_pipzap=False, preview_zap=False, checkParentalControl=True, ref=None):
2017 self.curRoot = self.startRoot
2018 nref = ref or self.getCurrentSelection()
2019 ref = self.session.nav.getCurrentlyPlayingServiceOrGroup()
2020 if enable_pipzap and self.dopipzap:
2021 ref = self.session.pip.getCurrentService()
2022 if ref is None or ref != nref:
2023 nref = self.session.pip.resolveAlternatePipService(nref)
2024 if nref and (not checkParentalControl or Components.ParentalControl.parentalControl.isServicePlayable(nref, boundFunction(self.zap, enable_pipzap=True, checkParentalControl=False))):
2025 self.session.pip.playService(nref)
2026 self.__evServiceStart()
2027 self.showPipzapMessage()
2029 self.setStartRoot(self.curRoot)
2030 self.setCurrentSelection(ref)
2031 elif ref is None or ref != nref:
2032 Screens.InfoBar.InfoBar.instance.checkTimeshiftRunning(boundFunction(self.zapCheckTimeshiftCallback, enable_pipzap, preview_zap, nref))
2033 elif not preview_zap:
2035 self.saveChannel(nref)
2036 config.servicelist.lastmode.save()
2037 self.setCurrentSelection(nref)
2038 if self.startServiceRef is None or nref != self.startServiceRef:
2039 self.addToHistory(nref)
2040 self.rootChanged = False
2041 self.revertMode = None
2043 def zapCheckTimeshiftCallback(self, enable_pipzap, preview_zap, nref, answer):
2045 self.new_service_played = True
2046 self.session.nav.playService(nref)
2049 self.saveChannel(nref)
2050 config.servicelist.lastmode.save()
2051 if self.startServiceRef is None or nref != self.startServiceRef:
2052 self.addToHistory(nref)
2054 self.setCurrentSelection(self.session.pip.getCurrentService())
2056 self.mainScreenMode = config.servicelist.lastmode.value
2057 self.mainScreenRoot = self.getRoot()
2058 self.revertMode = None
2060 Notifications.RemovePopup("Parental control")
2061 self.setCurrentSelection(nref)
2063 self.setStartRoot(self.curRoot)
2064 self.setCurrentSelection(self.session.nav.getCurrentlyPlayingServiceOrGroup())
2068 def newServicePlayed(self):
2069 ret = self.new_service_played
2070 self.new_service_played = False
2073 def addToHistory(self, ref):
2074 if self.servicePath is not None:
2075 tmp=self.servicePath[:]
2078 del self.history[self.history_pos+1:]
2081 self.history.append(tmp)
2082 hlen = len(self.history)
2083 if hlen > HISTORYSIZE:
2086 self.history_pos = hlen-1
2088 def historyBack(self):
2089 hlen = len(self.history)
2090 currentPlayedRef = self.session.nav.getCurrentlyPlayingServiceOrGroup()
2091 if hlen > 0 and currentPlayedRef and self.history[self.history_pos][-1] != currentPlayedRef:
2092 self.addToHistory(currentPlayedRef)
2093 hlen = len(self.history)
2094 if hlen > 1 and self.history_pos > 0:
2095 self.history_pos -= 1
2096 self.setHistoryPath()
2098 def historyNext(self):
2099 hlen = len(self.history)
2100 if hlen > 1 and self.history_pos < (hlen-1):
2101 self.history_pos += 1
2102 self.setHistoryPath()
2104 def setHistoryPath(self, doZap=True):
2105 path = self.history[self.history_pos][:]
2107 del self.servicePath[:]
2108 self.servicePath += path
2111 cur_root = self.getRoot()
2112 if cur_root and cur_root != root:
2115 self.session.nav.playService(ref)
2117 self.setCurrentSelection(self.session.pip.getCurrentService())
2119 self.setCurrentSelection(ref)
2120 self.saveChannel(ref)
2124 for i in self.servicePath:
2125 path += i.toString()
2127 if path and path != self.lastroot.value:
2128 if self.mode == MODE_RADIO and 'FROM BOUQUET "bouquets.tv"' in path:
2130 elif self.mode == MODE_TV and 'FROM BOUQUET "bouquets.radio"' in path:
2132 self.lastroot.value = path
2133 self.lastroot.save()
2135 def restoreRoot(self):
2136 tmp = [x for x in self.lastroot.value.split(';') if x != '']
2137 current = [x.toString() for x in self.servicePath]
2138 if tmp != current or self.rootChanged:
2142 self.servicePath.append(eServiceReference(i))
2145 path = self.servicePath.pop()
2146 self.enterPath(path)
2148 self.showFavourites()
2150 self.rootChanged = False
2152 def preEnterPath(self, refstr):
2153 if self.servicePath and self.servicePath[0] != eServiceReference(refstr):
2154 pathstr = self.lastroot.value
2155 if pathstr is not None and refstr in pathstr:
2157 lastservice = eServiceReference(self.lastservice.value)
2158 if lastservice.valid():
2159 self.setCurrentSelection(lastservice)
2163 def saveChannel(self, ref):
2165 refstr = ref.toString()
2168 if refstr != self.lastservice.value:
2169 self.lastservice.value = refstr
2170 self.lastservice.save()
2172 def setCurrentServicePath(self, path, doZap=True):
2174 self.history[self.history_pos] = path
2176 self.history.append(path)
2177 self.setHistoryPath(doZap)
2179 def getCurrentServicePath(self):
2181 return self.history[self.history_pos]
2184 def recallPrevService(self):
2185 hlen = len(self.history)
2186 currentPlayedRef = self.session.nav.getCurrentlyPlayingServiceOrGroup()
2187 if hlen > 0 and currentPlayedRef and self.history[self.history_pos][-1] != currentPlayedRef:
2188 self.addToHistory(currentPlayedRef)
2189 hlen = len(self.history)
2191 if self.history_pos == hlen-1:
2192 tmp = self.history[self.history_pos]
2193 self.history[self.history_pos] = self.history[self.history_pos-1]
2194 self.history[self.history_pos-1] = tmp
2196 tmp = self.history[self.history_pos+1]
2197 self.history[self.history_pos+1] = self.history[self.history_pos]
2198 self.history[self.history_pos] = tmp
2199 self.setHistoryPath()
2202 if self.revertMode is None:
2205 # This unfortunately won't work with subservices
2206 self.setCurrentSelection(self.session.pip.getCurrentService())
2208 lastservice = eServiceReference(self.lastservice.value)
2209 if lastservice.valid() and self.getCurrentSelection() != lastservice:
2210 self.setCurrentSelection(lastservice)
2213 self.correctChannelNumber()
2214 self.editMode = False
2215 self.protectContextMenu = True
2219 playingref = self.session.nav.getCurrentlyPlayingServiceOrGroup()
2220 if self.startServiceRef and (playingref is None or playingref != self.startServiceRef):
2221 self.setStartRoot(self.startRoot)
2222 self.new_service_played = True
2223 self.session.nav.playService(self.startServiceRef)
2224 self.saveChannel(self.startServiceRef)
2227 self.startServiceRef = None
2228 self.startRoot = None
2230 # This unfortunately won't work with subservices
2231 self.setCurrentSelection(self.session.pip.getCurrentService())
2233 self.setCurrentSelection(playingref)
2235 def setStartRoot(self, root):
2237 if self.revertMode == MODE_TV:
2239 elif self.revertMode == MODE_RADIO:
2241 self.revertMode = None
2242 self.enterUserbouquet(root)
2244 def restoreMode(self):
2245 if self.revertMode == MODE_TV:
2247 elif self.revertMode == MODE_RADIO:
2249 self.revertMode = None
2251 def correctChannelNumber(self):
2252 current_ref = self.session.nav.getCurrentlyPlayingServiceOrGroup()
2254 tmp_mode = config.servicelist.lastmode.value
2255 tmp_root = self.getRoot()
2256 tmp_ref = self.getCurrentSelection()
2257 pip_ref = self.session.pip.getCurrentService()
2258 if tmp_ref and pip_ref and tmp_ref != pip_ref:
2259 self.revertMode = None
2261 if self.mainScreenMode == "tv":
2263 elif self.mainScreenMode == "radio":
2265 if self.mainScreenRoot:
2266 self.setRoot(self.mainScreenRoot)
2267 self.setCurrentSelection(current_ref)
2268 selected_ref = self.getCurrentSelection()
2269 if selected_ref and current_ref and selected_ref.getChannelNum() != current_ref.getChannelNum():
2270 oldref = self.session.nav.currentlyPlayingServiceReference
2271 if oldref and selected_ref == oldref or (oldref != current_ref and selected_ref == current_ref):
2272 self.session.nav.currentlyPlayingServiceOrGroup = selected_ref
2273 self.session.nav.pnav.navEvent(iPlayableService.evStart)
2275 if tmp_mode == "tv":
2277 elif tmp_mode == "radio":
2279 self.enterUserbouquet(tmp_root)
2280 title = self.instance.getTitle()
2281 pos = title.find(" (")
2284 title += _(" (PiP)")
2285 self.setTitle(title)
2286 self.buildTitleString()
2287 if tmp_ref and pip_ref and tmp_ref.getChannelNum() != pip_ref.getChannelNum():
2288 self.session.pip.currentService = tmp_ref
2289 self.setCurrentSelection(tmp_ref)
2290 self.revertMode = None
2292 class RadioInfoBar(Screen):
2293 def __init__(self, session):
2294 Screen.__init__(self, session)
2295 self["RdsDecoder"] = RdsDecoder(self.session.nav)
2297 class ChannelSelectionRadio(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelectionEPG, InfoBarBase, SelectionEventInfo):
2298 ALLOW_SUSPEND = True
2300 def __init__(self, session, infobar):
2301 ChannelSelectionBase.__init__(self, session)
2302 ChannelSelectionEdit.__init__(self)
2303 ChannelSelectionEPG.__init__(self)
2304 InfoBarBase.__init__(self)
2305 SelectionEventInfo.__init__(self)
2306 self.infobar = infobar
2307 self.startServiceRef = None
2308 self.onLayoutFinish.append(self.onCreate)
2310 self.info = session.instantiateDialog(RadioInfoBar) # our simple infobar
2312 self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"],
2314 "keyTV": self.cancel,
2315 "keyRadio": self.cancel,
2316 "cancel": self.cancel,
2317 "ok": self.channelSelected,
2320 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
2322 iPlayableService.evStart: self.__evServiceStart,
2323 iPlayableService.evEnd: self.__evServiceEnd
2326 ########## RDS Radiotext / Rass Support BEGIN
2327 self.infobar = infobar # reference to real infobar (the one and only)
2328 self["RdsDecoder"] = self.info["RdsDecoder"]
2329 self["RdsActions"] = HelpableActionMap(self, "InfobarRdsActions",
2331 "startRassInteractive": (self.startRassInteractive, _("View Rass interactive..."))
2333 self["RdsActions"].setEnabled(False)
2334 infobar.rds_display.onRassInteractivePossibilityChanged.append(self.RassInteractivePossibilityChanged)
2335 self.onClose.append(self.__onClose)
2336 self.onExecBegin.append(self.__onExecBegin)
2337 self.onExecEnd.append(self.__onExecEnd)
2339 def __onClose(self):
2340 lastservice = eServiceReference(config.tv.lastservice.value)
2341 self.session.nav.playService(lastservice)
2343 def startRassInteractive(self):
2345 self.infobar.rass_interactive = self.session.openWithCallback(self.RassInteractiveClosed, RassInteractive)
2347 def RassInteractiveClosed(self):
2349 self.infobar.rass_interactive = None
2350 self.infobar.RassSlidePicChanged()
2352 def RassInteractivePossibilityChanged(self, state):
2353 self["RdsActions"].setEnabled(state)
2354 ########## RDS Radiotext / Rass Support END
2356 def __onExecBegin(self):
2359 def __onExecEnd(self):
2363 self.infobar.rds_display.onRassInteractivePossibilityChanged.remove(self.RassInteractivePossibilityChanged)
2365 #set previous tv service
2368 def __evServiceStart(self):
2369 service = self.session.nav.getCurrentService()
2371 info = service.info()
2373 refstr = info.getInfoString(iServiceInformation.sServiceref)
2374 self.servicelist.setPlayableIgnoreService(eServiceReference(refstr))
2376 def __evServiceEnd(self):
2377 self.servicelist.setPlayableIgnoreService(eServiceReference())
2381 for i in self.servicePathRadio:
2382 path += i.toString()
2384 if path and path != config.radio.lastroot.value:
2385 config.radio.lastroot.value = path
2386 config.radio.lastroot.save()
2388 def restoreRoot(self):
2389 tmp = [x for x in config.radio.lastroot.value.split(';') if x != '']
2390 current = [x.toString() for x in self.servicePath]
2391 if tmp != current or self.rootChanged:
2394 self.servicePathRadio.append(eServiceReference(i))
2397 path = self.servicePathRadio.pop()
2398 self.enterPath(path)
2400 self.showFavourites()
2402 self.rootChanged = False
2404 def preEnterPath(self, refstr):
2405 if self.servicePathRadio and self.servicePathRadio[0] != eServiceReference(refstr):
2406 pathstr = config.radio.lastroot.value
2407 if pathstr is not None and refstr in pathstr:
2409 lastservice = eServiceReference(config.radio.lastservice.value)
2410 if lastservice.valid():
2411 self.setCurrentSelection(lastservice)
2418 lastservice = eServiceReference(config.radio.lastservice.value)
2419 if lastservice.valid():
2420 self.servicelist.setCurrent(lastservice)
2421 self.session.nav.playService(lastservice)
2423 self.session.nav.stopService()
2426 def channelSelected(self, doClose=False): # just return selected service
2427 ref = self.getCurrentSelection()
2429 self.toggleMoveMarked()
2430 elif (ref.flags & eServiceReference.flagDirectory) == eServiceReference.flagDirectory:
2432 self.gotoCurrentServiceOrProvider(ref)
2433 elif self.bouquet_mark_edit != OFF:
2434 if not (self.bouquet_mark_edit == EDIT_ALTERNATIVES and ref.flags & eServiceReference.isGroup):
2436 elif not (ref.flags & eServiceReference.isMarker): # no marker
2437 cur_root = self.getRoot()
2438 if not cur_root or not (cur_root.flags & eServiceReference.isGroup):
2439 playingref = self.session.nav.getCurrentlyPlayingServiceOrGroup()
2440 if playingref is None or playingref != ref:
2441 self.session.nav.playService(ref)
2442 config.radio.lastservice.value = ref.toString()
2443 config.radio.lastservice.save()
2447 self.channelSelected()
2449 class SimpleChannelSelection(ChannelSelectionBase):
2450 def __init__(self, session, title, currentBouquet=False):
2451 ChannelSelectionBase.__init__(self, session)
2452 self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"],
2454 "cancel": self.close,
2455 "ok": self.channelSelected,
2456 "keyRadio": self.setModeRadio,
2457 "keyTV": self.setModeTv,
2459 self.bouquet_mark_edit = OFF
2461 self.currentBouquet = currentBouquet
2462 self.onLayoutFinish.append(self.layoutFinished)
2464 def layoutFinished(self):
2466 if self.currentBouquet:
2467 ref = Screens.InfoBar.InfoBar.instance.servicelist.getRoot()
2470 self.gotoCurrentServiceOrProvider(ref)
2475 def keyRecord(self):
2478 def channelSelected(self): # just return selected service
2479 ref = self.getCurrentSelection()
2480 if (ref.flags & eServiceReference.flagDirectory) == eServiceReference.flagDirectory:
2482 self.gotoCurrentServiceOrProvider(ref)
2483 elif not (ref.flags & eServiceReference.isMarker):
2484 ref = self.getCurrentSelection()
2487 def setModeTv(self):
2489 self.showFavourites()
2491 def setModeRadio(self):
2493 self.showFavourites()