2 from Plugins.Plugin import PluginDescriptor
3 import NavigationInstance
5 from Screens.Screen import Screen
6 from Screens.InfoBar import InfoBar
7 from Screens.MessageBox import MessageBox
8 from Screens.PictureInPicture import on_pip_start_stop
10 from Components.NimManager import nimmanager
11 from Components.config import config, getConfigListEntry, ConfigSubsection, ConfigYesNo, ConfigSelection
12 from Components.ConfigList import ConfigListScreen
13 from Components.ActionMap import ActionMap
14 from Components.Sources.StaticText import StaticText
15 from Components.ServiceEventTracker import ServiceEventTracker
17 from enigma import iPlayableService, iServiceInformation, eEnv, eTimer, eServiceReference, iRecordableService
22 from enigma import eFCCServiceManager
24 g_max_fcc = len(glob.glob('/dev/fcc?'))
25 g_default_fcc = (g_max_fcc) > 5 and 5 or g_max_fcc
27 config.plugins.fccsetup = ConfigSubsection()
28 config.plugins.fccsetup.activate = ConfigYesNo(default = False)
29 config.plugins.fccsetup.maxfcc = ConfigSelection(default = str(g_default_fcc), choices = list((str(n), str(n)) for n in range(2, g_max_fcc+1)))
30 config.plugins.fccsetup.zapupdown = ConfigYesNo(default = True)
31 config.plugins.fccsetup.history = ConfigYesNo(default = False)
32 config.plugins.fccsetup.priority = ConfigSelection(default = "zapupdown", choices = { "zapupdown" : _("Zap Up/Down"), "historynextback" : _("History Prev/Next") })
33 config.plugins.fccsetup.disableforrec = ConfigYesNo(default = True)
39 FccInstance.FCCSetupChanged()
41 def checkSupportFCC():
43 return bool(g_max_fcc)
46 def __init__(self, session):
47 self.session = session
49 self.fccmgr = eFCCServiceManager.getInstance();
53 self.createListTimer = eTimer()
54 self.createListTimer.callback.append(self.FCCCreateList)
56 self.getSrefTimer = eTimer()
57 self.getSrefTimer.callback.append(self.FCCGetCurSref)
60 self.fccEventTimer = eTimer()
61 self.fccEventTimer.callback.append(self.FCCApplyEvent)
63 self.fccForceStartTimer = eTimer()
64 self.fccForceStartTimer.callback.append(self.FCCForceStart)
66 self.fccResetTimer = eTimer()
67 self.fccResetTimer.callback.append(self.FCCResetTimerForREC)
69 self.activating = False
71 self.fccSetupActivate = checkSupportFCC() and config.plugins.fccsetup.activate.value
72 self.maxFCC = int(config.plugins.fccsetup.maxfcc.value)
73 self.zapdownEnable = config.plugins.fccsetup.zapupdown.value
74 self.historyEnable = config.plugins.fccsetup.history.value
75 self.priority = config.plugins.fccsetup.priority.value
76 self.disableforrec = config.plugins.fccsetup.disableforrec.value
77 self.fccmgr.setFCCEnable(int(self.fccSetupActivate))
79 self.setProcFCC(self.fccSetupActivate)
80 self.fccTimeoutTimer = eTimer()
81 self.fccTimeoutTimer.callback.append(self.FCCTimeout)
82 self.fccTimeoutEventCode = 0x102
83 self.fccTimeoutWait = None
85 self.fccmgr.m_fcc_event.get().append(self.FCCGetEvent)
89 self.__event_tracker = None
91 self.changeEventTracker()
93 on_pip_start_stop.append(self.FCCForceStopforPIP)
95 def setProcFCC(self, value):
96 procPath = "/proc/stb/frontend/fbc/fcc"
97 if os.access(procPath, os.W_OK):
98 fd = open(procPath,'w')
99 fd.write(value and "enable" or "disable")
102 print "[FCCSupport] write fail! : ", procPath
104 def gotRecordEvent(self, service, event):
105 if self.disableforrec:
106 if (not self.recordings) and (event == iRecordableService.evTuneStart):
109 self.FCCForceStopForREC()
111 elif event == iRecordableService.evEnd:
113 if not self.recordings:
116 if event == iRecordableService.evTuneStart:
117 self.FCCForceStopAndStart()
119 elif event == iRecordableService.evEnd:
120 self.fccForceStartTimer.stop()
121 self.fccResetTimer.start(2000, True)
123 def FCCForceStart(self):
124 self.enableEventTracker(True)
128 def FCCForceStop(self):
129 self.enableEventTracker(False)
130 self.FCCDisableServices()
131 self.FCCStopAllServices()
133 def FCCForceStopAndStart(self):
134 self.fccResetTimer.stop()
136 self.fccForceStartTimer.start(2000, True)
138 def FCCForceStopforPIP(self):
139 self.FCCForceStopAndStart()
141 def FCCForceStopForREC(self):
144 def FCCResetTimerForREC(self):
145 self.FCCForceStopForREC()
148 def FCCSetupChanged(self):
151 newFccSetupActivate = checkSupportFCC() and config.plugins.fccsetup.activate.value
152 if self.fccSetupActivate != newFccSetupActivate:
153 self.fccSetupActivate = newFccSetupActivate
154 self.setProcFCC(self.fccSetupActivate)
157 if int(config.plugins.fccsetup.maxfcc.value) != self.maxFCC:
158 self.maxFCC = int(config.plugins.fccsetup.maxfcc.value)
161 if self.zapdownEnable != config.plugins.fccsetup.zapupdown.value:
162 self.zapdownEnable = config.plugins.fccsetup.zapupdown.value
165 if self.historyEnable != config.plugins.fccsetup.history.value:
166 self.historyEnable = config.plugins.fccsetup.history.value
169 if self.priority != config.plugins.fccsetup.priority.value:
170 self.priority = config.plugins.fccsetup.priority.value
173 if self.disableforrec != config.plugins.fccsetup.disableforrec.value:
174 self.disableforrec = config.plugins.fccsetup.disableforrec.value
178 self.changeEventTracker()
180 if (not self.fccSetupActivate) or (self.disableforrec and self.recordings):
181 self.FCCDisableServices()
184 self.fccmgr.setFCCEnable(int(self.fccSetupActivate))
185 curPlaying = self.session.nav.getCurrentlyPlayingServiceReference()
187 self.session.nav.stopService()
188 self.session.nav.playService(curPlaying)
190 # get current recording state
191 def getRecordings(self):
192 self.recordings = bool(self.session.nav.getRecordings())
194 def addRecordEventCallback(self, enable=True):
196 if self.gotRecordEvent not in self.session.nav.record_event:
197 self.session.nav.record_event.append(self.gotRecordEvent)
199 if self.gotRecordEvent in self.session.nav.record_event:
200 self.session.nav.record_event.remove(self.gotRecordEvent)
202 def changeEventTracker(self):
203 if self.fccSetupActivate:
204 self.addRecordEventCallback(True)
205 if self.disableforrec and self.recordings:
206 self.enableEventTracker(False)
208 self.enableEventTracker(True)
210 self.addRecordEventCallback(False)
211 self.enableEventTracker(False)
213 def enableEventTracker(self, activate):
215 if not self.__event_tracker:
216 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
218 iPlayableService.evStart: self.getEvStart,
219 iPlayableService.evEnd: self.getEvEnd,
220 iPlayableService.evTunedIn: self.getEvTunedIn,
221 iPlayableService.evTuneFailed: self.getEvTuneFailed
224 elif self.__event_tracker:
225 # run ServiceEventTracker.__del_event()
226 for x in self.onClose:
230 self.__event_tracker = None
232 def getEvStart(self):
233 self.createListTimer.start(0,True)
236 self.FCCDisableServices()
238 def getEvTunedIn(self):
241 def getEvTuneFailed(self):
244 def isPlayableFCC(self, sref):
246 if isinstance(sref, str):
247 sref = eServiceReference(sref)
252 elif sref.getPath(): # is PVR? or streaming?
255 elif int(sref.getData(0)) in (2, 10): # is RADIO?
260 def getZapUpDownList(self):
261 fccZapUpDownList = []
262 serviceList = InfoBar.instance.servicelist.servicelist.getList()
263 curServiceRef = InfoBar.instance.servicelist.servicelist.getCurrent().toString()
266 for idx in range(len(serviceList)):
267 sref = serviceList[idx].toString()
268 if (sref.split(':')[1] == '0') and self.isPlayableFCC(sref) : # remove marker
269 serviceRefList.append(sref)
271 if curServiceRef in serviceRefList:
272 serviceRefListSize = len(serviceRefList)
273 curServiceIndex = serviceRefList.index(curServiceRef)
275 for x in range(self.maxFCC-1):
276 if x > (serviceRefListSize-2): # if not ((x+1) <= (serviceRefListSize-1))
281 idx *= -1 # idx : [ 1, -1, 2, -2, 3, -3, 4, -4 ....]
282 idx = (curServiceIndex+idx) % serviceRefListSize # calc wraparound
284 fccZapUpDownList.append(serviceRefList[idx])
286 print "[FCCCreateList] append error, idx : %d" % idx
289 return fccZapUpDownList
291 def getHistoryPrevNextList(self):
293 history = InfoBar.instance.servicelist.history[:]
294 history_pos = InfoBar.instance.servicelist.history_pos
295 history_len = len(history)
297 if history_len > 1 and history_pos > 0:
298 historyPrev = history[history_pos-1][:][-1].toString()
299 if self.isPlayableFCC(historyPrev):
300 historyList.append(historyPrev)
302 if history_len > 1 and history_pos < (history_len-1):
303 historyNext = history[history_pos+1][:][-1].toString()
304 if self.isPlayableFCC(historyNext):
305 historyList.append(historyNext)
309 def FCCCreateList(self):
310 if (not self.fccSetupActivate) or (self.disableforrec and self.recordings):
315 fccZapUpDownList = []
318 if self.zapdownEnable:
319 fccZapUpDownList = self.getZapUpDownList()
321 if self.historyEnable:
322 historyList = self.getHistoryPrevNextList()
324 if self.priority == "zapupdown":
325 fccZapDownLen = len(fccZapUpDownList)
327 size = fccZapDownLen > 2 and 2 or fccZapDownLen
328 self.fccList = fccZapUpDownList[:size]
329 fccZapUpDownList = fccZapUpDownList[size:]
331 self.addFCCList(historyList)
332 self.addFCCList(fccZapUpDownList)
334 self.addFCCList(historyList)
335 self.addFCCList(fccZapUpDownList)
337 self.FCCReconfigureFccList()
339 def addFCCList(self, newlist):
340 fccListMaxLen = self.maxFCC-1
342 if len(self.fccList) >= fccListMaxLen:
345 if sref not in self.fccList:
346 self.fccList.append(sref)
348 def FCCReconfigureFccList(self):
350 currentFCCList = self.fccmgr.getFCCServiceList()
352 for (sref, value) in currentFCCList.items():
355 if state == 2: # fcc_state_failed
356 stopFCCList.append(sref)
358 elif sref in self.fccList: # check conflict FCC channel (decoder/prepare)
359 self.fccList.remove(sref)
361 elif state == 0: # fcc_state_preparing
362 stopFCCList.append(sref)
364 for sref in stopFCCList:
365 self.fccmgr.stopFCCService(eServiceReference(sref))
367 def FCCTryStart(self):
368 self.getSrefTimer.start(0, True)
370 def FCCGetCurSref(self):
371 if (not self.fccSetupActivate) or (self.disableforrec and self.recordings):
374 if self.createListTimer.isActive():
375 self.createListTimer.stop()
378 curSref = self.session.nav.getCurrentlyPlayingServiceReference()
380 if curSref and self.isPlayableFCC(curSref):
383 print "[FCCSupport][FCCGetCurSref] get current serviceReference failed!!"
386 self.activating = True
387 self.FCCGetEvent(iPlayableService.evTunedIn)
389 def FCCGetEvent(self, event):
390 if self.activating and event in (iPlayableService.evTunedIn, iPlayableService.evTuneFailed, iPlayableService.evFccFailed, self.fccTimeoutEventCode):
391 self.eventList.append(event)
392 self.fccEventTimer.start(0, True)
394 def FCCApplyEvent(self):
395 if not self.activating:
398 while self.eventList:
399 event = self.eventList.pop(0)
401 self.FCCTimeoutTimerStop()
403 if event in (iPlayableService.evTuneFailed, iPlayableService.evFccFailed):
404 self.fccmgr.stopFCCService() # stop FCC Services in failed state
406 if not self.FCCCheckAndTimerStart() and len(self.fccList):
407 sref = self.fccList.pop(0)
408 if self.isPlayableFCC(sref): # remove PVR, streaming, radio channels
409 self.fccmgr.playFCCService(eServiceReference(sref))
410 self.FCCTimeoutTimerStart(sref)
412 def FCCStopAllServices(self):
413 self.FCCTimeoutTimerStop()
414 fccServiceList = self.fccmgr.getFCCServiceList()
415 for (sref, value) in fccServiceList.items():
417 if state != 1 : # 1 : fcc_state_decoding
418 self.fccmgr.stopFCCService(eServiceReference(sref))
420 def FCCDisableServices(self):
421 self.FCCTimeoutTimerStop()
422 self.getSrefTimer.stop()
423 self.activating = False
426 self.fccEventTimer.stop()
427 self.fccmgr.stopFCCService()
430 def FCCCheckNoLocked(self):
431 for (sref, value) in self.fccmgr.getFCCServiceList().items():
434 if state != 1 and locked == 0: # no fcc decoding and no locked
438 def FCCTimeout(self):
439 sref = self.FCCCheckNoLocked()
440 if sref and sref == self.fccTimeoutWait:
441 self.fccmgr.stopFCCService(eServiceReference(sref))
442 self.FCCGetEvent(self.fccTimeoutEventCode)
444 def FCCCheckAndTimerStart(self):
445 sref = self.FCCCheckNoLocked()
447 self.FCCTimeoutTimerStart(sref)
451 def FCCTimeoutTimerStart(self, sref):
452 self.fccTimeoutWait = sref
453 self.fccTimeoutTimer.start(5000, True)
455 def FCCTimeoutTimerStop(self):
456 self.fccTimeoutWait = None
457 self.fccTimeoutTimer.stop()
459 class FCCSetup(Screen, ConfigListScreen):
461 <screen position="center,center" size="590,320" >
462 <ePixmap pixmap="skin_default/buttons/red.png" position="90,15" size="140,40" alphatest="on" />
463 <ePixmap pixmap="skin_default/buttons/green.png" position="360,15" size="140,40" alphatest="on" />
464 <widget source="key_red" render="Label" position="90,15" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" foregroundColor="#ffffff" transparent="1" />
465 <widget source="key_green" render="Label" position="360,15" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" foregroundColor="#ffffff" transparent="1" />
466 <widget name="config" zPosition="2" position="15,80" size="560,140" scrollbarMode="showOnDemand" transparent="1" />
467 <widget source="description" render="Label" position="30,240" size="530,60" font="Regular;24" halign="center" valign="center" />
471 def __init__(self,session):
472 Screen.__init__(self,session)
473 self.title = _("Fast Channel Change Setup")
474 self.session = session
475 self["shortcuts"] = ActionMap(["ShortcutActions", "SetupActions" ],
478 "cancel": self.keyCancel,
479 "red": self.keyCancel,
480 "green": self.keySave,
483 ConfigListScreen.__init__(self, self.list,session = self.session)
484 self["key_red"] = StaticText(_("Cancel"))
485 self["key_green"] = StaticText(_("Save"))
487 self.isSupport = checkSupportFCC()
490 self["description"] = StaticText("")
494 self["description"] = StaticText(_("Box or driver is not support FCC."))
496 def createConfig(self):
497 self.enableEntry = getConfigListEntry(_("FCC enabled"), config.plugins.fccsetup.activate)
498 self.fccmaxEntry = getConfigListEntry(_("Max Channels"), config.plugins.fccsetup.maxfcc)
499 self.zapupdownEntry = getConfigListEntry(_("Zap Up/Down"), config.plugins.fccsetup.zapupdown)
500 self.historyEntry = getConfigListEntry(_("History Prev/Next"), config.plugins.fccsetup.history)
501 self.priorityEntry = getConfigListEntry(_("priority"), config.plugins.fccsetup.priority)
502 self.recEntry = getConfigListEntry(_("Disable FCC during recordings"), config.plugins.fccsetup.disableforrec)
504 def createSetup(self):
506 self.list.append( self.enableEntry )
507 if self.enableEntry[1].value:
508 self.list.append( self.fccmaxEntry )
509 self.list.append( self.zapupdownEntry )
510 self.list.append( self.historyEntry )
511 if self.zapupdownEntry[1].value and self.historyEntry[1].value:
512 self.list.append( self.priorityEntry )
513 self.list.append(self.recEntry)
515 self["config"].list = self.list
516 self["config"].l.setList(self.list)
519 ConfigListScreen.keyLeft(self)
523 ConfigListScreen.keyRight(self)
526 def setupChanged(self):
527 currentEntry = self["config"].getCurrent()
528 if currentEntry in (self.zapupdownEntry, self.historyEntry, self.enableEntry):
529 if not (self.zapupdownEntry[1].value or self.historyEntry[1].value):
530 if currentEntry == self.historyEntry:
531 self.zapupdownEntry[1].value = True
533 self.historyEntry[1].value = True
534 elif self.zapupdownEntry[1].value and self.historyEntry[1].value:
535 if int(self.fccmaxEntry[1].value) < 5:
537 self.fccmaxEntry[1].value = str(g_max_fcc)
539 self.fccmaxEntry[1].value = str(5)
544 if not self.isSupport:
548 ConfigListScreen.keySave(self)
551 def getExtensionName():
552 if config.plugins.fccsetup.activate.value:
553 return _("Disable FastChannelChange")
555 return _("Enable FastChannelChange")
558 if config.plugins.fccsetup.activate.value:
559 config.plugins.fccsetup.activate.value = False
561 config.plugins.fccsetup.activate.value = True
562 config.plugins.fccsetup.activate.save()
565 def FCCSupportInit(reason, **kwargs):
566 if kwargs.has_key("session"):
568 FccInstance = FCCSupport(kwargs["session"])
570 def addExtentions(infobarExtensions):
571 infobarExtensions.addExtension((getExtensionName, ToggleUpdate, lambda: True), None)
573 def main(session, **kwargs):
574 session.open(FCCSetup)
576 def Plugins(**kwargs):
582 PluginDescriptor(name="FCCSupport",
583 description="Fast Channel Change Support",
584 where = [PluginDescriptor.WHERE_SESSIONSTART],
585 fnc = FCCSupportInit))
588 PluginDescriptor(name="FCCExtensionMenu",
589 description="Fast Channel Change Extension Menu",
590 where = [PluginDescriptor.WHERE_EXTENSIONSINGLE],
591 fnc = addExtentions))
594 PluginDescriptor(name=_("FCCSetup"),
595 description=_("Fast Channel Change Setup"),
596 where = [PluginDescriptor.WHERE_PLUGINMENU],
597 needsRestart = False,