1 from enigma import eTimer, eDVBSatelliteEquipmentControl, eDVBResourceManager, \
2 eDVBDiseqcCommand, eDVBFrontendParametersSatellite, eDVBFrontendParameters,\
5 from Screens.Screen import Screen
6 from Screens.ScanSetup import ScanSetup
7 from Screens.MessageBox import MessageBox
8 from Plugins.Plugin import PluginDescriptor
10 from Components.Label import Label
11 from Components.ConfigList import ConfigList
12 from Components.TunerInfo import TunerInfo
13 from Components.ActionMap import ActionMap
14 from Components.NimManager import nimmanager
15 from Components.MenuList import MenuList
16 from Components.config import ConfigSatlist, ConfigNothing, ConfigSelection, ConfigSubsection, KEY_LEFT, KEY_RIGHT, getConfigListEntry
18 from time import sleep
20 class PositionerSetup(Screen):
22 <screen position="100,100" size="560,400" title="Positioner setup..." >
23 <widget name="list" position="100,0" size="350,155" />
25 <widget name="red" position="0,155" size="140,80" backgroundColor="red" halign="center" valign="center" font="Regular;21" />
26 <widget name="green" position="140,155" size="140,80" backgroundColor="green" halign="center" valign="center" font="Regular;21" />
27 <widget name="yellow" position="280,155" size="140,80" backgroundColor="yellow" halign="center" valign="center" font="Regular;21" />
28 <widget name="blue" position="420,155" size="140,80" backgroundColor="blue" halign="center" valign="center" font="Regular;21" />
30 <widget name="snr" text="SNR:" position="0,245" size="60,22" font="Regular;21" />
31 <widget name="agc" text="AGC:" position="0,270" size="60,22" font="Regular;21" />
32 <widget name="ber" text="BER:" position="0,295" size="60,22" font="Regular;21" />
33 <widget name="lock" text="Lock:" position="0,320" size="60,22" font="Regular;21" />
34 <widget name="snr_percentage" position="220,245" size="60,22" font="Regular;21" />
35 <widget name="agc_percentage" position="220,270" size="60,22" font="Regular;21" />
36 <widget name="ber_value" position="220,295" size="60,22" font="Regular;21" />
37 <widget name="lock_state" position="60,320" size="150,22" font="Regular;21" />
38 <widget name="snr_bar" position="60,245" size="150,22" />
39 <widget name="agc_bar" position="60,270" size="150,22" />
40 <widget name="ber_bar" position="60,295" size="150,22" />
42 <widget name="frequency" text="Frequency:" position="300,245" size="120,22" font="Regular;21" />
43 <widget name="symbolrate" text="Symbolrate:" position="300,270" size="120,22" font="Regular;21" />
44 <widget name="fec" text="FEC:" position="300,295" size="120,22" font="Regular;21" />
45 <widget name="frequency_value" position="420,245" size="120,22" font="Regular;21" />
46 <widget name="symbolrate_value" position="420,270" size="120,22" font="Regular;21" />
47 <widget name="fec_value" position="420,295" size="120,22" font="Regular;21" />
49 def __init__(self, session, feid):
50 self.skin = PositionerSetup.skin
51 Screen.__init__(self, session)
55 if not self.openFrontend():
56 self.oldref = session.nav.getCurrentlyPlayingServiceReference()
57 session.nav.stopService() # try to disable foreground service
58 if not self.openFrontend():
59 if session.pipshown: # try to disable pip
60 session.pipshown = False
62 if not self.openFrontend():
63 self.frontend = None # in normal case this should not happen
65 self.frontendStatus = { }
67 self.diseqc = Diseqc(self.frontend)
68 self.tuner = Tuner(self.frontend)
69 self.tuner.tune((0,0,0,0,0,0))
74 self.stopOnLock = False
77 self["red"] = self.red
78 self.green = Label("")
79 self["green"] = self.green
80 self.yellow = Label("")
81 self["yellow"] = self.yellow
83 self["blue"] = self.blue
86 self["list"] = ConfigList(self.list)
92 self["lock"] = Label()
93 self["snr_percentage"] = TunerInfo(TunerInfo.SNR_PERCENTAGE, statusDict = self.frontendStatus)
94 self["agc_percentage"] = TunerInfo(TunerInfo.AGC_PERCENTAGE, statusDict = self.frontendStatus)
95 self["ber_value"] = TunerInfo(TunerInfo.BER_VALUE, statusDict = self.frontendStatus)
96 self["snr_bar"] = TunerInfo(TunerInfo.SNR_BAR, statusDict = self.frontendStatus)
97 self["agc_bar"] = TunerInfo(TunerInfo.AGC_BAR, statusDict = self.frontendStatus)
98 self["ber_bar"] = TunerInfo(TunerInfo.BER_BAR, statusDict = self.frontendStatus)
99 self["lock_state"] = TunerInfo(TunerInfo.LOCK_STATE, statusDict = self.frontendStatus)
101 self["frequency"] = Label()
102 self["symbolrate"] = Label()
103 self["fec"] = Label()
105 self["frequency_value"] = Label("")
106 self["symbolrate_value"] = Label("")
107 self["fec_value"] = Label("")
109 self["actions"] = ActionMap(["DirectionActions", "OkCancelActions", "ColorActions"],
112 "cancel": self.keyCancel,
118 "green": self.greenKey,
119 "yellow": self.yellowKey,
120 "blue": self.blueKey,
123 self.updateColors("tune")
125 self.statusTimer = eTimer()
126 self.statusTimer.callback.append(self.updateStatus)
127 self.statusTimer.start(50, True)
128 self.onClose.append(self.__onClose)
131 self.session.nav.playService(self.oldref)
133 def restartPrevService(self, yesno):
144 self.session.openWithCallback(self.restartPrevService, MessageBox, _("Zap back to service before positioner setup?"), MessageBox.TYPE_YESNO)
146 self.restartPrevService(False)
148 def openFrontend(self):
149 res_mgr = eDVBResourceManager.getInstance()
151 self.raw_channel = res_mgr.allocateRawChannel(self.feid)
153 self.frontend = self.raw_channel.getFrontend()
157 print "getFrontend failed"
159 print "getRawChannel failed"
161 print "getResourceManager instance failed"
164 def createConfig(self):
165 self.positioner_tune = ConfigNothing()
166 self.positioner_move = ConfigNothing()
167 self.positioner_finemove = ConfigNothing()
168 self.positioner_limits = ConfigNothing()
169 self.positioner_goto0 = ConfigNothing()
171 for x in range(1,255):
172 storepos.append(str(x))
173 self.positioner_storage = ConfigSelection(choices = storepos)
175 def createSetup(self):
176 self.list.append((_("Tune"), self.positioner_tune, "tune"))
177 self.list.append((_("Positioner movement"), self.positioner_move, "move"))
178 self.list.append((_("Positioner fine movement"), self.positioner_finemove, "finemove"))
179 self.list.append((_("Set limits"), self.positioner_limits, "limits"))
180 self.list.append((_("Positioner storage"), self.positioner_storage, "storage"))
181 self.list.append((_("Goto 0"), self.positioner_goto0, "goto0"))
182 self["list"].l.setList(self.list)
187 def getCurrentConfigPath(self):
188 return self["list"].getCurrent()[2]
191 if not self.isMoving:
192 self["list"].instance.moveSelection(self["list"].instance.moveUp)
193 self.updateColors(self.getCurrentConfigPath())
196 if not self.isMoving:
197 self["list"].instance.moveSelection(self["list"].instance.moveDown)
198 self.updateColors(self.getCurrentConfigPath())
201 self["list"].handleKey(KEY_LEFT)
204 self["list"].handleKey(KEY_RIGHT)
206 def updateColors(self, entry):
208 self.red.setText(_("Tune"))
209 self.green.setText("")
210 self.yellow.setText("")
211 self.blue.setText("")
212 elif entry == "move":
214 self.red.setText(_("Stop"))
215 self.green.setText(_("Stop"))
216 self.yellow.setText(_("Stop"))
217 self.blue.setText(_("Stop"))
219 self.red.setText(_("Move west"))
220 self.green.setText(_("Search west"))
221 self.yellow.setText(_("Search east"))
222 self.blue.setText(_("Move east"))
223 elif entry == "finemove":
225 self.green.setText(_("Step west"))
226 self.yellow.setText(_("Step east"))
227 self.blue.setText("")
228 elif entry == "limits":
229 self.red.setText(_("Limits off"))
230 self.green.setText(_("Limit west"))
231 self.yellow.setText(_("Limit east"))
232 self.blue.setText(_("Limits on"))
233 elif entry == "storage":
235 self.green.setText(_("Store position"))
236 self.yellow.setText(_("Goto position"))
237 self.blue.setText("")
238 elif entry == "goto0":
239 self.red.setText(_("Goto 0"))
240 self.green.setText("")
241 self.yellow.setText("")
242 self.blue.setText("")
245 self.green.setText("")
246 self.yellow.setText("")
247 self.blue.setText("")
250 entry = self.getCurrentConfigPath()
253 self.diseqccommand("stop")
254 self.isMoving = False
255 self.stopOnLock = False
257 self.diseqccommand("moveWest", 0)
259 self.updateColors("move")
260 elif entry == "limits":
261 self.diseqccommand("limitOff")
262 elif entry == "tune":
263 self.session.openWithCallback(self.tune, TunerScreen, self.feid)
264 elif entry == "goto0":
265 print "move to position 0"
266 self.diseqccommand("moveTo", 0)
269 entry = self.getCurrentConfigPath()
272 self.diseqccommand("stop")
273 self.isMoving = False
274 self.stopOnLock = False
277 self.stopOnLock = True
278 self.diseqccommand("moveWest", 0)
279 self.updateColors("move")
280 elif entry == "finemove":
281 print "stepping west"
282 self.diseqccommand("moveWest", 0xFF) # one step
283 elif entry == "storage":
284 print "store at position", int(self.positioner_storage.value)
285 self.diseqccommand("store", int(self.positioner_storage.value))
286 elif entry == "limits":
287 self.diseqccommand("limitWest")
290 entry = self.getCurrentConfigPath()
293 self.diseqccommand("stop")
294 self.isMoving = False
295 self.stopOnLock = False
298 self.stopOnLock = True
299 self.diseqccommand("moveEast", 0)
300 self.updateColors("move")
301 elif entry == "finemove":
302 print "stepping east"
303 self.diseqccommand("moveEast", 0xFF) # one step
304 elif entry == "storage":
305 print "move to position", int(self.positioner_storage.value)
306 self.diseqccommand("moveTo", int(self.positioner_storage.value))
307 elif entry == "limits":
308 self.diseqccommand("limitEast")
311 entry = self.getCurrentConfigPath()
314 self.diseqccommand("stop")
315 self.isMoving = False
316 self.stopOnLock = False
318 self.diseqccommand("moveEast", 0)
320 self.updateColors("move")
322 elif entry == "limits":
323 self.diseqccommand("limitOn")
325 def diseqccommand(self, cmd, param = 0):
326 self.diseqc.command(cmd, param)
329 def updateStatus(self):
331 self.frontend.getFrontendStatus(self.frontendStatus)
332 self["snr_percentage"].update()
333 self["agc_percentage"].update()
334 self["ber_value"].update()
335 self["snr_bar"].update()
336 self["agc_bar"].update()
337 self["ber_bar"].update()
338 self["lock_state"].update()
339 transponderdata = self.tuner.getTransponderData()
340 self["frequency_value"].setText(str(transponderdata.get("frequency")))
341 self["symbolrate_value"].setText(str(transponderdata.get("symbol_rate")))
342 self["fec_value"].setText(str(transponderdata.get("fec_inner")))
343 if self.frontendStatus.get("tuner_locked", 0) == 1 and self.isMoving and self.stopOnLock:
344 self.diseqccommand("stop")
345 self.isMoving = False
346 self.stopOnLock = False
347 self.updateColors(self.getCurrentConfigPath())
348 self.statusTimer.start(50, True)
350 def tune(self, transponder):
351 if transponder is not None:
352 self.tuner.tune(transponder)
355 def __init__(self, frontend):
356 self.frontend = frontend
358 def command(self, what, param = 0):
360 cmd = eDVBDiseqcCommand()
361 if what == "moveWest":
362 string = 'e03169' + ("%02x" % param)
363 elif what == "moveEast":
364 string = 'e03168' + ("%02x" % param)
365 elif what == "moveTo":
366 string = 'e0316b' + ("%02x" % param)
367 elif what == "store":
368 string = 'e0316a' + ("%02x" % param)
369 elif what == "limitOn":
371 elif what == "limitOff":
373 elif what == "limitEast":
375 elif what == "limitWest":
378 string = 'e03160' #positioner stop
380 print "diseqc command:",
382 cmd.setCommandString(string)
383 self.frontend.setTone(iDVBFrontend.toneOff)
384 sleep(0.015) # wait 15msec after disable tone
385 self.frontend.sendDiseqc(cmd)
386 if string == 'e03160': #positioner stop
388 self.frontend.sendDiseqc(cmd) # send 2nd time
391 def __init__(self, frontend):
392 self.frontend = frontend
394 def tune(self, transponder):
395 print "tuning to transponder with data", transponder
396 parm = eDVBFrontendParametersSatellite()
397 parm.frequency = transponder[0] * 1000
398 parm.symbol_rate = transponder[1] * 1000
399 parm.polarisation = transponder[2]
400 parm.fec = transponder[3]
401 parm.inversion = transponder[4]
402 parm.orbital_position = transponder[5]
403 parm.system = 0 # FIXMEE !! HARDCODED DVB-S (add support for DVB-S2)
404 parm.modulation = 1 # FIXMEE !! HARDCODED QPSK
405 feparm = eDVBFrontendParameters()
406 feparm.setDVBS(parm, True)
407 self.lastparm = feparm
409 self.frontend.tune(feparm)
413 self.frontend.tune(self.lastparm)
415 def getTransponderData(self):
418 self.frontend.getTransponderData(ret, True)
423 class TunerScreen(ScanSetup):
425 <screen position="90,100" size="520,400" title="Tune">
426 <widget name="config" position="20,10" size="460,350" scrollbarMode="showOnDemand" />
427 <widget name="introduction" position="20,360" size="350,30" font="Regular;23" />
430 def __init__(self, session, feid):
432 ScanSetup.__init__(self, session)
433 self["introduction"].setText("")
435 def createSetup(self):
436 self.typeOfTuningEntry = None
439 self.typeOfTuningEntry = getConfigListEntry(_('Tune'), tuning.type)
440 self.list.append(self.typeOfTuningEntry)
441 self.satEntry = getConfigListEntry(_('Satellite'), tuning.sat)
442 self.list.append(self.satEntry)
443 if tuning.type.value == "manual_transponder":
444 self.list.append(getConfigListEntry(_('Frequency'), self.scan_sat.frequency))
445 self.list.append(getConfigListEntry(_('Inversion'), self.scan_sat.inversion))
446 self.list.append(getConfigListEntry(_('Symbol Rate'), self.scan_sat.symbolrate))
447 self.list.append(getConfigListEntry(_("Polarity"), self.scan_sat.polarization))
448 self.list.append(getConfigListEntry(_("FEC"), self.scan_sat.fec))
449 elif tuning.type.value == "predefined_transponder":
450 self.list.append(getConfigListEntry(_("Transponder"), tuning.transponder))
451 self["config"].list = self.list
452 self["config"].l.setList(self.list)
455 if self["config"].getCurrent() == self.typeOfTuningEntry:
457 elif self["config"].getCurrent() == self.satEntry:
460 def createConfig(self, foo):
463 tuning = ConfigSubsection()
464 tuning.type = ConfigSelection(
465 default = "manual_transponder",
466 choices = { "manual_transponder" : _("Manual transponder"),
467 "predefined_transponder" : _("Predefined transponder") } )
468 tuning.sat = ConfigSatlist(list=nimmanager.getRotorSatListForNim(self.feid))
469 tuning.sat.addNotifier(self.tuningSatChanged)
470 self.updateTransponders()
471 TunerScreenConfigCreated = True
472 ScanSetup.createConfig(self, None)
474 def tuningSatChanged(self, *parm):
475 self.updateTransponders()
477 def updateTransponders(self):
478 if len(tuning.sat.choices):
479 transponderlist = nimmanager.getTransponders(int(tuning.sat.value))
482 for x in transponderlist:
517 tps.append(str(x[1]) + "," + str(x[2]) + "," + pol + "," + fec)
518 tuning.transponder = ConfigSelection(choices=tps)
521 returnvalue = (0, 0, 0, 0, 0, 0)
522 satpos = int(tuning.sat.value)
523 if tuning.type.value == "manual_transponder":
525 self.scan_sat.frequency.value,
526 self.scan_sat.symbolrate.value,
527 self.scan_sat.polarization.index,
528 self.scan_sat.fec.index,
529 self.scan_sat.inversion.index,
531 elif tuning.type.value == "predefined_transponder":
532 transponder = nimmanager.getTransponders(satpos)[tuning.transponder.index]
533 returnvalue = (int(transponder[1] / 1000), int(transponder[2] / 1000), transponder[3], transponder[4], 2, satpos)
534 self.close(returnvalue)
539 class RotorNimSelection(Screen):
541 <screen position="140,165" size="400,100" title="select Slot">
542 <widget name="nimlist" position="20,10" size="360,75" />
545 def __init__(self, session):
546 Screen.__init__(self, session)
548 nimlist = nimmanager.getNimListOfType("DVB-S")
551 nimMenuList.append((nimmanager.nim_slots[x].friendly_full_description, x))
553 self["nimlist"] = MenuList(nimMenuList)
555 self["actions"] = ActionMap(["OkCancelActions"],
557 "ok": self.okbuttonClick ,
561 def okbuttonClick(self):
562 selection = self["nimlist"].getCurrent()
563 self.session.open(PositionerSetup, selection[1])
565 def PositionerMain(session, **kwargs):
566 nimList = nimmanager.getNimListOfType("DVB-S")
567 if len(nimList) == 0:
568 session.open(MessageBox, _("No positioner capable frontend found."), MessageBox.TYPE_ERROR)
570 if session.nav.RecordTimer.isRecording():
571 session.open(MessageBox, _("A recording is currently running. Please stop the recording before trying to configure the positioner."), MessageBox.TYPE_ERROR)
575 configured_rotor_sats = nimmanager.getRotorSatListForNim(x)
576 if len(configured_rotor_sats) != 0:
578 if len(usableNims) == 1:
579 session.open(PositionerSetup, usableNims[0])
580 elif len(usableNims) > 1:
581 session.open(RotorNimSelection)
583 session.open(MessageBox, _("No tuner is configured for use with a diseqc positioner!"), MessageBox.TYPE_ERROR)
585 def PositionerSetupStart(menuid, **kwargs):
587 return [(_("Positioner setup"), PositionerMain, "positioner_setup", None)]
591 def Plugins(**kwargs):
592 if (nimmanager.hasNimType("DVB-S")):
593 return PluginDescriptor(name=_("Positioner setup"), description="Setup your positioner", where = PluginDescriptor.WHERE_MENU, fnc=PositionerSetupStart)