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)
236 if sref.getPath(): # is PVR? or streaming?
239 if int(sref.getData(0)) in (2, 10): # is RADIO?
244 def getZapUpDownList(self):
245 fccZapUpDownList = []
246 serviceList = InfoBar.instance.servicelist.servicelist.getList()
247 curServiceRef = InfoBar.instance.servicelist.servicelist.getCurrent().toString()
250 for idx in range(len(serviceList)):
251 sref = serviceList[idx].toString()
252 if (sref.split(':')[1] == '0') and self.isPlayableFCC(sref) : # remove marker
253 serviceRefList.append(sref)
255 if curServiceRef in serviceRefList:
256 serviceRefListSize = len(serviceRefList)
257 curServiceIndex = serviceRefList.index(curServiceRef)
259 for x in range(self.maxFCC-1):
260 if x > (serviceRefListSize-2): # if not ((x+1) <= (serviceRefListSize-1))
265 idx *= -1 # idx : [ 1, -1, 2, -2, 3, -3, 4, -4 ....]
266 idx = (curServiceIndex+idx) % serviceRefListSize # calc wraparound
268 fccZapUpDownList.append(serviceRefList[idx])
270 print "[FCCCreateList] append error, idx : %d" % idx
273 return fccZapUpDownList
275 def getHistoryPrevNextList(self):
277 history = InfoBar.instance.servicelist.history[:]
278 history_pos = InfoBar.instance.servicelist.history_pos
279 history_len = len(history)
281 if history_len > 1 and history_pos > 0:
282 historyPrev = history[history_pos-1][:][-1].toString()
283 if self.isPlayableFCC(historyPrev):
284 historyList.append(historyPrev)
286 if history_len > 1 and history_pos < (history_len-1):
287 historyNext = history[history_pos+1][:][-1].toString()
288 if self.isPlayableFCC(historyNext):
289 historyList.append(historyNext)
293 def FCCCreateList(self):
294 if (not self.fccSetupActivate) or (self.disableforrec and self.recordings):
299 fccZapUpDownList = []
302 if self.zapdownEnable:
303 fccZapUpDownList = self.getZapUpDownList()
305 if self.historyEnable:
306 historyList = self.getHistoryPrevNextList()
308 if self.priority == "zapupdown":
309 fccZapDownLen = len(fccZapUpDownList)
311 size = fccZapDownLen > 2 and 2 or fccZapDownLen
312 self.fccList = fccZapUpDownList[:size]
313 fccZapUpDownList = fccZapUpDownList[size:]
315 self.addFCCList(historyList)
316 self.addFCCList(fccZapUpDownList)
318 self.addFCCList(historyList)
319 self.addFCCList(fccZapUpDownList)
321 self.FCCReconfigureFccList()
323 def addFCCList(self, newlist):
324 fccListMaxLen = self.maxFCC-1
326 if len(self.fccList) >= fccListMaxLen:
329 if sref not in self.fccList:
330 self.fccList.append(sref)
332 def FCCReconfigureFccList(self):
334 currentFCCList = self.fccmgr.getFCCServiceList()
336 for (sref, value) in currentFCCList.items():
339 if state == 2: # fcc_state_failed
340 stopFCCList.append(sref)
342 elif sref in self.fccList: # check conflict FCC channel (decoder/prepare)
343 self.fccList.remove(sref)
345 elif state == 0: # fcc_state_preparing
346 stopFCCList.append(sref)
348 for sref in stopFCCList:
349 self.fccmgr.stopFCCService(eServiceReference(sref))
351 def FCCTryStart(self):
352 self.getSrefTimer.start(0, True)
354 def FCCGetCurSref(self):
355 if (not self.fccSetupActivate) or (self.disableforrec and self.recordings):
358 if self.createListTimer.isActive():
359 self.createListTimer.stop()
362 curSref = self.session.nav.getCurrentlyPlayingServiceReference()
364 if curSref and self.isPlayableFCC(curSref):
367 print "[FCCSupport][FCCGetCurSref] get current serviceReference failed!!"
370 self.activating = True
371 self.FCCGetEvent(iPlayableService.evTunedIn)
373 def FCCGetEvent(self, event):
374 if self.activating and event in (iPlayableService.evTunedIn, iPlayableService.evTuneFailed, iPlayableService.evFccFailed, self.fccTimeoutEventCode):
375 self.eventList.append(event)
376 self.fccEventTimer.start(0, True)
378 def FCCApplyEvent(self):
379 if not self.activating:
382 while self.eventList:
383 event = self.eventList.pop(0)
385 self.FCCTimeoutTimerStop()
387 if event in (iPlayableService.evTuneFailed, iPlayableService.evFccFailed):
388 self.fccmgr.stopFCCService() # stop FCC Services in failed state
390 if not self.FCCCheckAndTimerStart() and len(self.fccList):
391 sref = self.fccList.pop(0)
392 if self.isPlayableFCC(sref): # remove PVR, streaming, radio channels
393 self.fccmgr.playFCCService(eServiceReference(sref))
394 self.FCCTimeoutTimerStart(sref)
396 def FCCStopAllServices(self):
397 self.FCCTimeoutTimerStop()
398 fccServiceList = self.fccmgr.getFCCServiceList()
399 for (sref, value) in fccServiceList.items():
401 if state != 1 : # 1 : fcc_state_decoding
402 self.fccmgr.stopFCCService(eServiceReference(sref))
404 def FCCDisableServices(self):
405 self.FCCTimeoutTimerStop()
406 self.getSrefTimer.stop()
407 self.activating = False
410 self.fccEventTimer.stop()
411 self.fccmgr.stopFCCService()
414 def FCCForceStart(self):
418 def FCCCheckNoLocked(self):
419 for (sref, value) in self.fccmgr.getFCCServiceList().items():
422 if state != 1 and locked == 0: # no fcc decoding and no locked
426 def FCCTimeout(self):
427 sref = self.FCCCheckNoLocked()
428 if sref and sref == self.fccTimeoutWait:
429 self.fccmgr.stopFCCService(eServiceReference(sref))
430 self.FCCGetEvent(self.fccTimeoutEventCode)
432 def FCCCheckAndTimerStart(self):
433 sref = self.FCCCheckNoLocked()
435 self.FCCTimeoutTimerStart(sref)
439 def FCCTimeoutTimerStart(self, sref):
440 self.fccTimeoutWait = sref
441 self.fccTimeoutTimer.start(5000, True)
443 def FCCTimeoutTimerStop(self):
444 self.fccTimeoutWait = None
445 self.fccTimeoutTimer.stop()
447 class FCCSetup(Screen, ConfigListScreen):
449 <screen position="center,center" size="590,320" >
450 <ePixmap pixmap="skin_default/buttons/red.png" position="90,15" size="140,40" alphatest="on" />
451 <ePixmap pixmap="skin_default/buttons/green.png" position="360,15" size="140,40" alphatest="on" />
452 <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" />
453 <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" />
454 <widget name="config" zPosition="2" position="15,80" size="560,140" scrollbarMode="showOnDemand" transparent="1" />
455 <widget source="description" render="Label" position="30,240" size="530,60" font="Regular;24" halign="center" valign="center" />
459 def __init__(self,session):
460 Screen.__init__(self,session)
461 self.title = _("Fast Channel Change Setup")
462 self.session = session
463 self["shortcuts"] = ActionMap(["ShortcutActions", "SetupActions" ],
466 "cancel": self.keyCancel,
467 "red": self.keyCancel,
468 "green": self.keySave,
471 ConfigListScreen.__init__(self, self.list,session = self.session)
472 self["key_red"] = StaticText(_("Cancel"))
473 self["key_green"] = StaticText(_("Save"))
475 self.isSupport = checkSupportFCC()
478 self["description"] = StaticText("")
482 self["description"] = StaticText(_("Box or driver is not support FCC."))
484 def createConfig(self):
485 self.enableEntry = getConfigListEntry(_("FCC enabled"), config.plugins.fccsetup.activate)
486 self.fccmaxEntry = getConfigListEntry(_("Max Channels"), config.plugins.fccsetup.maxfcc)
487 self.zapupdownEntry = getConfigListEntry(_("Zap Up/Down"), config.plugins.fccsetup.zapupdown)
488 self.historyEntry = getConfigListEntry(_("History Prev/Next"), config.plugins.fccsetup.history)
489 self.priorityEntry = getConfigListEntry(_("priority"), config.plugins.fccsetup.priority)
490 self.recEntry = getConfigListEntry(_("Disable FCC during recordings"), config.plugins.fccsetup.disableforrec)
492 def createSetup(self):
494 self.list.append( self.enableEntry )
495 if self.enableEntry[1].value:
496 self.list.append( self.fccmaxEntry )
497 self.list.append( self.zapupdownEntry )
498 self.list.append( self.historyEntry )
499 if self.zapupdownEntry[1].value and self.historyEntry[1].value:
500 self.list.append( self.priorityEntry )
501 self.list.append(self.recEntry)
503 self["config"].list = self.list
504 self["config"].l.setList(self.list)
507 ConfigListScreen.keyLeft(self)
511 ConfigListScreen.keyRight(self)
514 def setupChanged(self):
515 currentEntry = self["config"].getCurrent()
516 if currentEntry in (self.zapupdownEntry, self.historyEntry, self.enableEntry):
517 if not (self.zapupdownEntry[1].value or self.historyEntry[1].value):
518 if currentEntry == self.historyEntry:
519 self.zapupdownEntry[1].value = True
521 self.historyEntry[1].value = True
522 elif self.zapupdownEntry[1].value and self.historyEntry[1].value:
523 if int(self.fccmaxEntry[1].value) < 5:
525 self.fccmaxEntry[1].value = str(g_max_fcc)
527 self.fccmaxEntry[1].value = str(5)
532 if not self.isSupport:
536 ConfigListScreen.keySave(self)
539 def getExtensionName():
540 if config.plugins.fccsetup.activate.value:
541 return _("Disable FastChannelChange")
543 return _("Enable FastChannelChange")
546 if config.plugins.fccsetup.activate.value:
547 config.plugins.fccsetup.activate.value = False
549 config.plugins.fccsetup.activate.value = True
550 config.plugins.fccsetup.activate.save()
553 def FCCSupportInit(reason, **kwargs):
554 if kwargs.has_key("session"):
556 FccInstance = FCCSupport(kwargs["session"])
558 def addExtentions(infobarExtensions):
559 infobarExtensions.addExtension((getExtensionName, ToggleUpdate, lambda: True), None)
561 def main(session, **kwargs):
562 session.open(FCCSetup)
564 def Plugins(**kwargs):
570 PluginDescriptor(name="FCCSupport",
571 description="Fast Channel Change Support",
572 where = [PluginDescriptor.WHERE_SESSIONSTART],
573 fnc = FCCSupportInit))
576 PluginDescriptor(name="FCCExtensionMenu",
577 description="Fast Channel Change Extension Menu",
578 where = [PluginDescriptor.WHERE_EXTENSIONSINGLE],
579 fnc = addExtentions))
582 PluginDescriptor(name=_("FCCSetup"),
583 description=_("Fast Channel Change Setup"),
584 where = [PluginDescriptor.WHERE_PLUGINMENU],
585 needsRestart = False,