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
9 from Components.NimManager import nimmanager
10 from Components.config import config, getConfigListEntry, ConfigSubsection, ConfigYesNo, ConfigSelection
11 from Components.ConfigList import ConfigListScreen
12 from Components.ActionMap import ActionMap
13 from Components.Sources.StaticText import StaticText
14 from Components.ServiceEventTracker import ServiceEventTracker
16 from enigma import iPlayableService, iServiceInformation, eEnv, eTimer, eServiceReference, iRecordableService
21 from enigma import eFCCServiceManager
23 g_max_fcc = len(glob.glob('/dev/fcc?'))
24 g_default_fcc = (g_max_fcc) > 5 and 5 or g_max_fcc
26 config.plugins.fccsetup = ConfigSubsection()
27 config.plugins.fccsetup.activate = ConfigYesNo(default = False)
28 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)))
29 config.plugins.fccsetup.zapupdown = ConfigYesNo(default = True)
30 config.plugins.fccsetup.history = ConfigYesNo(default = False)
31 config.plugins.fccsetup.priority = ConfigSelection(default = "zapupdown", choices = { "zapupdown" : _("Zap Up/Down"), "historynextback" : _("History Prev/Next") })
32 config.plugins.fccsetup.disableforrec = ConfigYesNo(default = True)
38 FccInstance.FCCSetupChanged()
40 def checkSupportFCC():
42 return bool(g_max_fcc)
45 def __init__(self, session):
46 self.session = session
48 self.fccmgr = eFCCServiceManager.getInstance();
52 self.createListTimer = eTimer()
53 self.createListTimer.callback.append(self.FCCCreateList)
55 self.getSrefTimer = eTimer()
56 self.getSrefTimer.callback.append(self.FCCGetCurSref)
59 self.fccEventTimer = eTimer()
60 self.fccEventTimer.callback.append(self.FCCApplyEvent)
62 self.fccForceStartTimer = eTimer()
63 self.fccForceStartTimer.callback.append(self.FCCForceStartForREC)
65 self.fccResetTimer = eTimer()
66 self.fccResetTimer.callback.append(self.FCCResetTimerForREC)
68 self.activating = False
70 self.fccSetupActivate = checkSupportFCC() and config.plugins.fccsetup.activate.value
71 self.maxFCC = int(config.plugins.fccsetup.maxfcc.value)
72 self.zapdownEnable = config.plugins.fccsetup.zapupdown.value
73 self.historyEnable = config.plugins.fccsetup.history.value
74 self.priority = config.plugins.fccsetup.priority.value
75 self.disableforrec = config.plugins.fccsetup.disableforrec.value
76 self.fccmgr.setFCCEnable(int(self.fccSetupActivate))
78 self.setProcFCC(self.fccSetupActivate)
79 self.fccTimeoutTimer = eTimer()
80 self.fccTimeoutTimer.callback.append(self.FCCTimeout)
81 self.fccTimeoutEventCode = 0x102
82 self.fccTimeoutWait = None
84 self.fccmgr.m_fcc_event.get().append(self.FCCGetEvent)
88 self.__event_tracker = None
90 self.changeEventTracker()
92 def setProcFCC(self, value):
93 procPath = "/proc/stb/frontend/fbc/fcc"
94 if os.access(procPath, os.W_OK):
95 fd = open(procPath,'w')
96 fd.write(value and "enable" or "disable")
99 print "[FCCSupport] write fail! : ", procPath
101 def gotRecordEvent(self, service, event):
102 if self.disableforrec:
103 if (not self.recordings) and (event == iRecordableService.evTuneStart):
106 self.FCCForceStopForREC()
108 elif event == iRecordableService.evEnd:
110 if not self.recordings:
111 self.FCCForceStartForREC()
113 if event == iRecordableService.evTuneStart:
114 self.fccResetTimer.stop()
115 self.FCCForceStopForREC()
116 self.fccForceStartTimer.start(2000, True)
118 elif event == iRecordableService.evEnd:
119 self.fccForceStartTimer.stop()
120 self.fccResetTimer.start(2000, True)
122 def FCCForceStopForREC(self):
123 self.enableEventTracker(False)
124 self.FCCDisableServices()
125 self.FCCStopAllServices()
127 def FCCForceStartForREC(self):
128 self.enableEventTracker(True)
131 def FCCResetTimerForREC(self):
132 self.FCCForceStopForREC()
133 self.FCCForceStartForREC()
135 def FCCSetupChanged(self):
138 newFccSetupActivate = checkSupportFCC() and config.plugins.fccsetup.activate.value
139 if self.fccSetupActivate != newFccSetupActivate:
140 self.fccSetupActivate = newFccSetupActivate
141 self.setProcFCC(self.fccSetupActivate)
144 if int(config.plugins.fccsetup.maxfcc.value) != self.maxFCC:
145 self.maxFCC = int(config.plugins.fccsetup.maxfcc.value)
148 if self.zapdownEnable != config.plugins.fccsetup.zapupdown.value:
149 self.zapdownEnable = config.plugins.fccsetup.zapupdown.value
152 if self.historyEnable != config.plugins.fccsetup.history.value:
153 self.historyEnable = config.plugins.fccsetup.history.value
156 if self.priority != config.plugins.fccsetup.priority.value:
157 self.priority = config.plugins.fccsetup.priority.value
160 if self.disableforrec != config.plugins.fccsetup.disableforrec.value:
161 self.disableforrec = config.plugins.fccsetup.disableforrec.value
165 self.changeEventTracker()
167 if (not self.fccSetupActivate) or (self.disableforrec and self.recordings):
168 self.FCCDisableServices()
171 self.fccmgr.setFCCEnable(int(self.fccSetupActivate))
172 curPlaying = self.session.nav.getCurrentlyPlayingServiceReference()
174 self.session.nav.stopService()
175 self.session.nav.playService(curPlaying)
177 # get current recording state
178 def getRecordings(self):
179 self.recordings = bool(self.session.nav.getRecordings())
181 def addRecordEventCallback(self, enable=True):
183 if self.gotRecordEvent not in self.session.nav.record_event:
184 self.session.nav.record_event.append(self.gotRecordEvent)
186 if self.gotRecordEvent in self.session.nav.record_event:
187 self.session.nav.record_event.remove(self.gotRecordEvent)
189 def changeEventTracker(self):
190 if self.fccSetupActivate:
191 self.addRecordEventCallback(True)
192 if self.disableforrec and self.recordings:
193 self.enableEventTracker(False)
195 self.enableEventTracker(True)
197 self.addRecordEventCallback(False)
198 self.enableEventTracker(False)
200 def enableEventTracker(self, activate):
202 if not self.__event_tracker:
203 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
205 iPlayableService.evStart: self.getEvStart,
206 iPlayableService.evEnd: self.getEvEnd,
207 iPlayableService.evTunedIn: self.getEvTunedIn,
208 iPlayableService.evTuneFailed: self.getEvTuneFailed
211 elif self.__event_tracker:
212 # run ServiceEventTracker.__del_event()
213 for x in self.onClose:
217 self.__event_tracker = None
219 def getEvStart(self):
220 self.createListTimer.start(0,True)
223 self.FCCDisableServices()
225 def getEvTunedIn(self):
228 def getEvTuneFailed(self):
231 def isPlayableFCC(self, sref):
233 if isinstance(sref, str):
234 sref = eServiceReference(sref)
239 elif sref.getPath(): # is PVR? or streaming?
242 elif int(sref.getData(0)) in (2, 10): # is RADIO?
247 def getZapUpDownList(self):
248 fccZapUpDownList = []
249 serviceList = InfoBar.instance.servicelist.servicelist.getList()
250 curServiceRef = InfoBar.instance.servicelist.servicelist.getCurrent().toString()
253 for idx in range(len(serviceList)):
254 sref = serviceList[idx].toString()
255 if (sref.split(':')[1] == '0') and self.isPlayableFCC(sref) : # remove marker
256 serviceRefList.append(sref)
258 if curServiceRef in serviceRefList:
259 serviceRefListSize = len(serviceRefList)
260 curServiceIndex = serviceRefList.index(curServiceRef)
262 for x in range(self.maxFCC-1):
263 if x > (serviceRefListSize-2): # if not ((x+1) <= (serviceRefListSize-1))
268 idx *= -1 # idx : [ 1, -1, 2, -2, 3, -3, 4, -4 ....]
269 idx = (curServiceIndex+idx) % serviceRefListSize # calc wraparound
271 fccZapUpDownList.append(serviceRefList[idx])
273 print "[FCCCreateList] append error, idx : %d" % idx
276 return fccZapUpDownList
278 def getHistoryPrevNextList(self):
280 history = InfoBar.instance.servicelist.history[:]
281 history_pos = InfoBar.instance.servicelist.history_pos
282 history_len = len(history)
284 if history_len > 1 and history_pos > 0:
285 historyPrev = history[history_pos-1][:][-1].toString()
286 if self.isPlayableFCC(historyPrev):
287 historyList.append(historyPrev)
289 if history_len > 1 and history_pos < (history_len-1):
290 historyNext = history[history_pos+1][:][-1].toString()
291 if self.isPlayableFCC(historyNext):
292 historyList.append(historyNext)
296 def FCCCreateList(self):
297 if (not self.fccSetupActivate) or (self.disableforrec and self.recordings):
302 fccZapUpDownList = []
305 if self.zapdownEnable:
306 fccZapUpDownList = self.getZapUpDownList()
308 if self.historyEnable:
309 historyList = self.getHistoryPrevNextList()
311 if self.priority == "zapupdown":
312 fccZapDownLen = len(fccZapUpDownList)
314 size = fccZapDownLen > 2 and 2 or fccZapDownLen
315 self.fccList = fccZapUpDownList[:size]
316 fccZapUpDownList = fccZapUpDownList[size:]
318 self.addFCCList(historyList)
319 self.addFCCList(fccZapUpDownList)
321 self.addFCCList(historyList)
322 self.addFCCList(fccZapUpDownList)
324 self.FCCReconfigureFccList()
326 def addFCCList(self, newlist):
327 fccListMaxLen = self.maxFCC-1
329 if len(self.fccList) >= fccListMaxLen:
332 if sref not in self.fccList:
333 self.fccList.append(sref)
335 def FCCReconfigureFccList(self):
337 currentFCCList = self.fccmgr.getFCCServiceList()
339 for (sref, value) in currentFCCList.items():
342 if state == 2: # fcc_state_failed
343 stopFCCList.append(sref)
345 elif sref in self.fccList: # check conflict FCC channel (decoder/prepare)
346 self.fccList.remove(sref)
348 elif state == 0: # fcc_state_preparing
349 stopFCCList.append(sref)
351 for sref in stopFCCList:
352 self.fccmgr.stopFCCService(eServiceReference(sref))
354 def FCCTryStart(self):
355 self.getSrefTimer.start(0, True)
357 def FCCGetCurSref(self):
358 if (not self.fccSetupActivate) or (self.disableforrec and self.recordings):
361 if self.createListTimer.isActive():
362 self.createListTimer.stop()
365 curSref = self.session.nav.getCurrentlyPlayingServiceReference()
367 if curSref and self.isPlayableFCC(curSref):
370 print "[FCCSupport][FCCGetCurSref] get current serviceReference failed!!"
373 self.activating = True
374 self.FCCGetEvent(iPlayableService.evTunedIn)
376 def FCCGetEvent(self, event):
377 if self.activating and event in (iPlayableService.evTunedIn, iPlayableService.evTuneFailed, iPlayableService.evFccFailed, self.fccTimeoutEventCode):
378 self.eventList.append(event)
379 self.fccEventTimer.start(0, True)
381 def FCCApplyEvent(self):
382 if not self.activating:
385 while self.eventList:
386 event = self.eventList.pop(0)
388 self.FCCTimeoutTimerStop()
390 if event in (iPlayableService.evTuneFailed, iPlayableService.evFccFailed):
391 self.fccmgr.stopFCCService() # stop FCC Services in failed state
393 if not self.FCCCheckAndTimerStart() and len(self.fccList):
394 sref = self.fccList.pop(0)
395 if self.isPlayableFCC(sref): # remove PVR, streaming, radio channels
396 self.fccmgr.playFCCService(eServiceReference(sref))
397 self.FCCTimeoutTimerStart(sref)
399 def FCCStopAllServices(self):
400 self.FCCTimeoutTimerStop()
401 fccServiceList = self.fccmgr.getFCCServiceList()
402 for (sref, value) in fccServiceList.items():
404 if state != 1 : # 1 : fcc_state_decoding
405 self.fccmgr.stopFCCService(eServiceReference(sref))
407 def FCCDisableServices(self):
408 self.FCCTimeoutTimerStop()
409 self.getSrefTimer.stop()
410 self.activating = False
413 self.fccEventTimer.stop()
414 self.fccmgr.stopFCCService()
417 def FCCForceStart(self):
421 def FCCCheckNoLocked(self):
422 for (sref, value) in self.fccmgr.getFCCServiceList().items():
425 if state != 1 and locked == 0: # no fcc decoding and no locked
429 def FCCTimeout(self):
430 sref = self.FCCCheckNoLocked()
431 if sref and sref == self.fccTimeoutWait:
432 self.fccmgr.stopFCCService(eServiceReference(sref))
433 self.FCCGetEvent(self.fccTimeoutEventCode)
435 def FCCCheckAndTimerStart(self):
436 sref = self.FCCCheckNoLocked()
438 self.FCCTimeoutTimerStart(sref)
442 def FCCTimeoutTimerStart(self, sref):
443 self.fccTimeoutWait = sref
444 self.fccTimeoutTimer.start(5000, True)
446 def FCCTimeoutTimerStop(self):
447 self.fccTimeoutWait = None
448 self.fccTimeoutTimer.stop()
450 class FCCSetup(Screen, ConfigListScreen):
452 <screen position="center,center" size="590,320" >
453 <ePixmap pixmap="skin_default/buttons/red.png" position="90,15" size="140,40" alphatest="on" />
454 <ePixmap pixmap="skin_default/buttons/green.png" position="360,15" size="140,40" alphatest="on" />
455 <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" />
456 <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" />
457 <widget name="config" zPosition="2" position="15,80" size="560,140" scrollbarMode="showOnDemand" transparent="1" />
458 <widget source="description" render="Label" position="30,240" size="530,60" font="Regular;24" halign="center" valign="center" />
462 def __init__(self,session):
463 Screen.__init__(self,session)
464 self.title = _("Fast Channel Change Setup")
465 self.session = session
466 self["shortcuts"] = ActionMap(["ShortcutActions", "SetupActions" ],
469 "cancel": self.keyCancel,
470 "red": self.keyCancel,
471 "green": self.keySave,
474 ConfigListScreen.__init__(self, self.list,session = self.session)
475 self["key_red"] = StaticText(_("Cancel"))
476 self["key_green"] = StaticText(_("Save"))
478 self.isSupport = checkSupportFCC()
481 self["description"] = StaticText("")
485 self["description"] = StaticText(_("Box or driver is not support FCC."))
487 def createConfig(self):
488 self.enableEntry = getConfigListEntry(_("FCC enabled"), config.plugins.fccsetup.activate)
489 self.fccmaxEntry = getConfigListEntry(_("Max Channels"), config.plugins.fccsetup.maxfcc)
490 self.zapupdownEntry = getConfigListEntry(_("Zap Up/Down"), config.plugins.fccsetup.zapupdown)
491 self.historyEntry = getConfigListEntry(_("History Prev/Next"), config.plugins.fccsetup.history)
492 self.priorityEntry = getConfigListEntry(_("priority"), config.plugins.fccsetup.priority)
493 self.recEntry = getConfigListEntry(_("Disable FCC during recordings"), config.plugins.fccsetup.disableforrec)
495 def createSetup(self):
497 self.list.append( self.enableEntry )
498 if self.enableEntry[1].value:
499 self.list.append( self.fccmaxEntry )
500 self.list.append( self.zapupdownEntry )
501 self.list.append( self.historyEntry )
502 if self.zapupdownEntry[1].value and self.historyEntry[1].value:
503 self.list.append( self.priorityEntry )
504 self.list.append(self.recEntry)
506 self["config"].list = self.list
507 self["config"].l.setList(self.list)
510 ConfigListScreen.keyLeft(self)
514 ConfigListScreen.keyRight(self)
517 def setupChanged(self):
518 currentEntry = self["config"].getCurrent()
519 if currentEntry in (self.zapupdownEntry, self.historyEntry, self.enableEntry):
520 if not (self.zapupdownEntry[1].value or self.historyEntry[1].value):
521 if currentEntry == self.historyEntry:
522 self.zapupdownEntry[1].value = True
524 self.historyEntry[1].value = True
525 elif self.zapupdownEntry[1].value and self.historyEntry[1].value:
526 if int(self.fccmaxEntry[1].value) < 5:
528 self.fccmaxEntry[1].value = str(g_max_fcc)
530 self.fccmaxEntry[1].value = str(5)
535 if not self.isSupport:
539 ConfigListScreen.keySave(self)
542 def getExtensionName():
543 if config.plugins.fccsetup.activate.value:
544 return _("Disable FastChannelChange")
546 return _("Enable FastChannelChange")
549 if config.plugins.fccsetup.activate.value:
550 config.plugins.fccsetup.activate.value = False
552 config.plugins.fccsetup.activate.value = True
553 config.plugins.fccsetup.activate.save()
556 def FCCSupportInit(reason, **kwargs):
557 if kwargs.has_key("session"):
559 FccInstance = FCCSupport(kwargs["session"])
561 def addExtentions(infobarExtensions):
562 infobarExtensions.addExtension((getExtensionName, ToggleUpdate, lambda: True), None)
564 def main(session, **kwargs):
565 session.open(FCCSetup)
567 def Plugins(**kwargs):
573 PluginDescriptor(name="FCCSupport",
574 description="Fast Channel Change Support",
575 where = [PluginDescriptor.WHERE_SESSIONSTART],
576 fnc = FCCSupportInit))
579 PluginDescriptor(name="FCCExtensionMenu",
580 description="Fast Channel Change Extension Menu",
581 where = [PluginDescriptor.WHERE_EXTENSIONSINGLE],
582 fnc = addExtentions))
585 PluginDescriptor(name=_("FCCSetup"),
586 description=_("Fast Channel Change Setup"),
587 where = [PluginDescriptor.WHERE_PLUGINMENU],
588 needsRestart = False,