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_db" position="60,245" size="150,22" halign="center" valign="center" font="Regular;21" />
31 <eLabel text="SNR:" position="0,270" size="60,22" font="Regular;21" />
32 <eLabel text="BER:" position="0,295" size="60,22" font="Regular;21" />
33 <eLabel text="Lock:" position="0,320" size="60,22" font="Regular;21" />
34 <widget name="snr_percentage" position="220,270" size="60,22" font="Regular;21" />
35 <widget name="ber_value" position="220,295" size="60,22" font="Regular;21" />
36 <widget name="lock_state" position="60,320" size="150,22" font="Regular;21" />
37 <widget name="snr_bar" position="60,270" size="150,22" />
38 <widget name="ber_bar" position="60,295" size="150,22" />
40 <eLabel text="Frequency:" position="300,245" size="120,22" font="Regular;21" />
41 <eLabel text="Symbolrate:" position="300,270" size="120,22" font="Regular;21" />
42 <eLabel text="FEC:" position="300,295" size="120,22" font="Regular;21" />
43 <widget name="frequency_value" position="420,245" size="120,22" font="Regular;21" />
44 <widget name="symbolrate_value" position="420,270" size="120,22" font="Regular;21" />
45 <widget name="fec_value" position="420,295" size="120,22" font="Regular;21" />
47 def __init__(self, session, feid):
48 self.skin = PositionerSetup.skin
49 Screen.__init__(self, session)
54 if not self.openFrontend():
55 self.oldref = session.nav.getCurrentlyPlayingServiceReference()
56 service = session.nav.getCurrentService()
57 feInfo = service and service.frontendInfo()
59 cur = feInfo.getTransponderData(True)
62 session.nav.stopService() # try to disable foreground service
63 if not self.openFrontend():
64 if session.pipshown: # try to disable pip
65 service = self.session.pip.pipservice
66 feInfo = service and service.frontendInfo()
68 cur = feInfo.getTransponderData()
71 session.pipshown = False
73 if not self.openFrontend():
74 self.frontend = None # in normal case this should not happen
76 self.frontendStatus = { }
77 self.diseqc = Diseqc(self.frontend)
78 self.tuner = Tuner(self.frontend)
80 tp = ( cur.get("frequency", 0) / 1000,
81 cur.get("symbol_rate", 0) / 1000,
82 { "HORIZONTAL" : 0, "VERTICAL" : 1,
83 "CIRCULAR_LEFT" : 2, "CIRCULAR_RIGHT" : 3 }[cur.get("polarization", "HORIZONTAL")],
84 { "FEC_AUTO" : 0, "FEC_1_2" : 1, "FEC_2_3" : 2, "FEC_3_4" : 3,
85 "FEC_5_6" : 4, "FEC_7_8" : 5, "FEC_8_9" : 6, "FEC_3_5" : 7,
86 "FEC_4_5" : 8, "FEC_9_10" : 9, "FEC_NONE" : 15 }[cur.get("fec_inner", "FEC_AUTO")],
87 { "INVERSION_OFF" : 0,
89 "INVERSION_AUTO" : 2 }[cur.get("inversion", "INVERSION_AUTO")],
90 cur.get("orbital_position", 0),
91 { "DVB-S" : 0, "DVB-S2" : 1 }[cur.get("system", "DVB-S")],
92 { "QPSK" : 1, "8PSK" : 2 }[cur.get("modulation", "QPSK")],
93 { "ROLLOFF_0_35" : 0, "ROLLOFF_0_25" : 1,
94 "ROLLOFF_0_20" : 2 }[cur.get("rolloff", "ROLLOFF_0_35")],
95 { "PILOT_OFF" : 0, "PILOT_ON" : 1,
96 "PILOT_AUTO" : 2 }[cur.get("pilot", "PILOT_AUTO")]
103 self.isMoving = False
104 self.stopOnLock = False
107 self["red"] = self.red
108 self.green = Label("")
109 self["green"] = self.green
110 self.yellow = Label("")
111 self["yellow"] = self.yellow
112 self.blue = Label("")
113 self["blue"] = self.blue
116 self["list"] = ConfigList(self.list)
119 self["snr_db"] = TunerInfo(TunerInfo.SNR_DB, statusDict = self.frontendStatus)
120 self["snr_percentage"] = TunerInfo(TunerInfo.SNR_PERCENTAGE, statusDict = self.frontendStatus)
121 self["ber_value"] = TunerInfo(TunerInfo.BER_VALUE, statusDict = self.frontendStatus)
122 self["snr_bar"] = TunerInfo(TunerInfo.SNR_BAR, statusDict = self.frontendStatus)
123 self["ber_bar"] = TunerInfo(TunerInfo.BER_BAR, statusDict = self.frontendStatus)
124 self["lock_state"] = TunerInfo(TunerInfo.LOCK_STATE, statusDict = self.frontendStatus)
126 self["frequency_value"] = Label("")
127 self["symbolrate_value"] = Label("")
128 self["fec_value"] = Label("")
130 self["actions"] = ActionMap(["DirectionActions", "OkCancelActions", "ColorActions"],
133 "cancel": self.keyCancel,
139 "green": self.greenKey,
140 "yellow": self.yellowKey,
141 "blue": self.blueKey,
144 self.updateColors("tune")
146 self.statusTimer = eTimer()
147 self.statusTimer.callback.append(self.updateStatus)
148 self.statusTimer.start(50, True)
149 self.onClose.append(self.__onClose)
152 self.session.nav.playService(self.oldref)
154 def restartPrevService(self, yesno):
165 self.session.openWithCallback(self.restartPrevService, MessageBox, _("Zap back to service before positioner setup?"), MessageBox.TYPE_YESNO)
167 self.restartPrevService(False)
169 def openFrontend(self):
170 res_mgr = eDVBResourceManager.getInstance()
172 self.raw_channel = res_mgr.allocateRawChannel(self.feid)
174 self.frontend = self.raw_channel.getFrontend()
178 print "getFrontend failed"
180 print "getRawChannel failed"
182 print "getResourceManager instance failed"
185 def createConfig(self):
186 self.positioner_tune = ConfigNothing()
187 self.positioner_move = ConfigNothing()
188 self.positioner_finemove = ConfigNothing()
189 self.positioner_limits = ConfigNothing()
190 self.positioner_goto0 = ConfigNothing()
192 for x in range(1,255):
193 storepos.append(str(x))
194 self.positioner_storage = ConfigSelection(choices = storepos)
196 def createSetup(self):
197 self.list.append((_("Tune"), self.positioner_tune, "tune"))
198 self.list.append((_("Positioner movement"), self.positioner_move, "move"))
199 self.list.append((_("Positioner fine movement"), self.positioner_finemove, "finemove"))
200 self.list.append((_("Set limits"), self.positioner_limits, "limits"))
201 self.list.append((_("Positioner storage"), self.positioner_storage, "storage"))
202 self.list.append((_("Goto 0"), self.positioner_goto0, "goto0"))
203 self["list"].l.setList(self.list)
208 def getCurrentConfigPath(self):
209 return self["list"].getCurrent()[2]
212 if not self.isMoving:
213 self["list"].instance.moveSelection(self["list"].instance.moveUp)
214 self.updateColors(self.getCurrentConfigPath())
217 if not self.isMoving:
218 self["list"].instance.moveSelection(self["list"].instance.moveDown)
219 self.updateColors(self.getCurrentConfigPath())
222 self["list"].handleKey(KEY_LEFT)
225 self["list"].handleKey(KEY_RIGHT)
227 def updateColors(self, entry):
229 self.red.setText(_("Tune"))
230 self.green.setText("")
231 self.yellow.setText("")
232 self.blue.setText("")
233 elif entry == "move":
235 self.red.setText(_("Stop"))
236 self.green.setText(_("Stop"))
237 self.yellow.setText(_("Stop"))
238 self.blue.setText(_("Stop"))
240 self.red.setText(_("Move west"))
241 self.green.setText(_("Search west"))
242 self.yellow.setText(_("Search east"))
243 self.blue.setText(_("Move east"))
244 elif entry == "finemove":
246 self.green.setText(_("Step west"))
247 self.yellow.setText(_("Step east"))
248 self.blue.setText("")
249 elif entry == "limits":
250 self.red.setText(_("Limits off"))
251 self.green.setText(_("Limit west"))
252 self.yellow.setText(_("Limit east"))
253 self.blue.setText(_("Limits on"))
254 elif entry == "storage":
256 self.green.setText(_("Store position"))
257 self.yellow.setText(_("Goto position"))
258 self.blue.setText("")
259 elif entry == "goto0":
260 self.red.setText(_("Goto 0"))
261 self.green.setText("")
262 self.yellow.setText("")
263 self.blue.setText("")
266 self.green.setText("")
267 self.yellow.setText("")
268 self.blue.setText("")
271 entry = self.getCurrentConfigPath()
274 self.diseqccommand("stop")
275 self.isMoving = False
276 self.stopOnLock = False
278 self.diseqccommand("moveWest", 0)
280 self.updateColors("move")
281 elif entry == "limits":
282 self.diseqccommand("limitOff")
283 elif entry == "tune":
285 self.frontend.getFrontendData(fe_data)
286 self.frontend.getTransponderData(fe_data, True)
287 feparm = self.tuner.lastparm.getDVBS()
288 fe_data["orbital_position"] = feparm.orbital_position
289 self.session.openWithCallback(self.tune, TunerScreen, self.feid, fe_data)
290 elif entry == "goto0":
291 print "move to position 0"
292 self.diseqccommand("moveTo", 0)
295 entry = self.getCurrentConfigPath()
298 self.diseqccommand("stop")
299 self.isMoving = False
300 self.stopOnLock = False
303 self.stopOnLock = True
304 self.diseqccommand("moveWest", 0)
305 self.updateColors("move")
306 elif entry == "finemove":
307 print "stepping west"
308 self.diseqccommand("moveWest", 0xFF) # one step
309 elif entry == "storage":
310 print "store at position", int(self.positioner_storage.value)
311 self.diseqccommand("store", int(self.positioner_storage.value))
313 elif entry == "limits":
314 self.diseqccommand("limitWest")
317 entry = self.getCurrentConfigPath()
320 self.diseqccommand("stop")
321 self.isMoving = False
322 self.stopOnLock = False
325 self.stopOnLock = True
326 self.diseqccommand("moveEast", 0)
327 self.updateColors("move")
328 elif entry == "finemove":
329 print "stepping east"
330 self.diseqccommand("moveEast", 0xFF) # one step
331 elif entry == "storage":
332 print "move to position", int(self.positioner_storage.value)
333 self.diseqccommand("moveTo", int(self.positioner_storage.value))
334 elif entry == "limits":
335 self.diseqccommand("limitEast")
338 entry = self.getCurrentConfigPath()
341 self.diseqccommand("stop")
342 self.isMoving = False
343 self.stopOnLock = False
345 self.diseqccommand("moveEast", 0)
347 self.updateColors("move")
349 elif entry == "limits":
350 self.diseqccommand("limitOn")
352 def diseqccommand(self, cmd, param = 0):
353 self.diseqc.command(cmd, param)
356 def updateStatus(self):
358 self.frontend.getFrontendStatus(self.frontendStatus)
359 self["snr_db"].update()
360 self["snr_percentage"].update()
361 self["ber_value"].update()
362 self["snr_bar"].update()
363 self["ber_bar"].update()
364 self["lock_state"].update()
365 transponderdata = self.tuner.getTransponderData()
366 self["frequency_value"].setText(str(transponderdata.get("frequency")))
367 self["symbolrate_value"].setText(str(transponderdata.get("symbol_rate")))
368 self["fec_value"].setText(str(transponderdata.get("fec_inner")))
369 if self.frontendStatus.get("tuner_locked", 0) == 1 and self.isMoving and self.stopOnLock:
370 self.diseqccommand("stop")
371 self.isMoving = False
372 self.stopOnLock = False
373 self.updateColors(self.getCurrentConfigPath())
374 self.statusTimer.start(50, True)
376 def tune(self, transponder):
377 if transponder is not None:
378 self.tuner.tune(transponder)
381 def __init__(self, frontend):
382 self.frontend = frontend
384 def command(self, what, param = 0):
386 cmd = eDVBDiseqcCommand()
387 if what == "moveWest":
388 string = 'e03169' + ("%02x" % param)
389 elif what == "moveEast":
390 string = 'e03168' + ("%02x" % param)
391 elif what == "moveTo":
392 string = 'e0316b' + ("%02x" % param)
393 elif what == "store":
394 string = 'e0316a' + ("%02x" % param)
395 elif what == "limitOn":
397 elif what == "limitOff":
399 elif what == "limitEast":
401 elif what == "limitWest":
404 string = 'e03160' #positioner stop
406 print "diseqc command:",
408 cmd.setCommandString(string)
409 self.frontend.setTone(iDVBFrontend.toneOff)
410 sleep(0.015) # wait 15msec after disable tone
411 self.frontend.sendDiseqc(cmd)
412 if string == 'e03160': #positioner stop
414 self.frontend.sendDiseqc(cmd) # send 2nd time
417 def __init__(self, frontend):
418 self.frontend = frontend
420 def tune(self, transponder):
421 print "tuning to transponder with data", transponder
422 parm = eDVBFrontendParametersSatellite()
423 parm.frequency = transponder[0] * 1000
424 parm.symbol_rate = transponder[1] * 1000
425 parm.polarisation = transponder[2]
426 parm.fec = transponder[3]
427 parm.inversion = transponder[4]
428 parm.orbital_position = transponder[5]
429 parm.system = transponder[6]
430 parm.modulation = transponder[7]
431 parm.rolloff = transponder[8]
432 parm.pilot = transponder[9]
433 feparm = eDVBFrontendParameters()
434 feparm.setDVBS(parm, True)
435 self.lastparm = feparm
437 self.frontend.tune(feparm)
441 self.frontend.tune(self.lastparm)
443 def getTransponderData(self):
446 self.frontend.getTransponderData(ret, True)
451 class TunerScreen(ScanSetup):
453 <screen position="90,100" size="520,400" title="Tune">
454 <widget name="config" position="20,10" size="460,350" scrollbarMode="showOnDemand" />
455 <widget name="introduction" position="20,360" size="350,30" font="Regular;23" />
458 def __init__(self, session, feid, fe_data):
460 self.fe_data = fe_data
461 ScanSetup.__init__(self, session)
462 self["introduction"].setText("")
464 def createSetup(self):
465 self.typeOfTuningEntry = None
468 self.typeOfTuningEntry = getConfigListEntry(_('Tune'), tuning.type)
469 self.list.append(self.typeOfTuningEntry)
470 self.satEntry = getConfigListEntry(_('Satellite'), tuning.sat)
471 self.list.append(self.satEntry)
472 nim = nimmanager.nim_slots[self.feid]
473 self.systemEntry = None
475 if tuning.type.value == "manual_transponder":
476 if nim.isCompatible("DVB-S2"):
477 self.systemEntry = getConfigListEntry(_('System'), self.scan_sat.system)
478 self.list.append(self.systemEntry)
480 # downgrade to dvb-s, in case a -s2 config was active
481 self.scan_sat.system.value = "dvb-s"
482 self.list.append(getConfigListEntry(_('Frequency'), self.scan_sat.frequency))
483 self.list.append(getConfigListEntry(_('Inversion'), self.scan_sat.inversion))
484 self.list.append(getConfigListEntry(_('Symbol Rate'), self.scan_sat.symbolrate))
485 self.list.append(getConfigListEntry(_("Polarity"), self.scan_sat.polarization))
486 if self.scan_sat.system.value == "dvb-s":
487 self.list.append(getConfigListEntry(_("FEC"), self.scan_sat.fec))
488 elif self.scan_sat.system.value == "dvb-s2":
489 self.list.append(getConfigListEntry(_("FEC"), self.scan_sat.fec_s2))
490 self.modulationEntry = getConfigListEntry(_('Modulation'), self.scan_sat.modulation)
491 self.list.append(self.modulationEntry)
492 self.list.append(getConfigListEntry(_('Rolloff'), self.scan_sat.rolloff))
493 self.list.append(getConfigListEntry(_('Pilot'), self.scan_sat.pilot))
494 elif tuning.type.value == "predefined_transponder":
495 self.list.append(getConfigListEntry(_("Transponder"), tuning.transponder))
496 self["config"].list = self.list
497 self["config"].l.setList(self.list)
500 if self["config"].getCurrent() in (self.typeOfTuningEntry, self.satEntry, self.systemEntry):
503 def createConfig(self, foo):
506 tuning = ConfigSubsection()
507 tuning.type = ConfigSelection(
508 default = "manual_transponder",
509 choices = { "manual_transponder" : _("Manual transponder"),
510 "predefined_transponder" : _("Predefined transponder") } )
511 tuning.sat = ConfigSatlist(list=nimmanager.getRotorSatListForNim(self.feid))
512 tuning.sat.addNotifier(self.tuningSatChanged)
513 self.updateTransponders()
514 orb_pos = self.fe_data.get("orbital_position", None)
515 if orb_pos is not None:
516 for x in nimmanager.getRotorSatListForNim(self.feid):
518 if x[0] == orb_pos and tuning.sat.value != opos:
519 tuning.sat.value = opos
520 del self.fe_data["orbital_position"]
521 ScanSetup.createConfig(self, self.fe_data)
523 def tuningSatChanged(self, *parm):
524 self.updateTransponders()
526 def updateTransponders(self):
527 if len(tuning.sat.choices):
528 transponderlist = nimmanager.getTransponders(int(tuning.sat.value))
531 for x in transponderlist:
566 tps.append(str(x[1]) + "," + str(x[2]) + "," + pol + "," + fec)
567 tuning.transponder = ConfigSelection(choices=tps)
570 returnvalue = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
571 satpos = int(tuning.sat.value)
572 if tuning.type.value == "manual_transponder":
573 if self.scan_sat.system.value == "dvb-s2":
574 fec = self.scan_sat.fec_s2.value
576 fec = self.scan_sat.fec.value
578 self.scan_sat.frequency.value,
579 self.scan_sat.symbolrate.value,
580 self.scan_sat.polarization.index,
592 self.scan_sat.inversion.index,
594 self.scan_sat.system.index,
595 self.scan_sat.modulation.index == 1 and 2 or 1,
596 self.scan_sat.rolloff.index,
597 self.scan_sat.pilot.index)
598 elif tuning.type.value == "predefined_transponder":
599 transponder = nimmanager.getTransponders(satpos)[tuning.transponder.index]
600 returnvalue = (transponder[1] / 1000, transponder[2] / 1000,
601 transponder[3], transponder[4], 2, satpos, transponder[5], transponder[6], transponder[8], transponder[9])
602 self.close(returnvalue)
607 class RotorNimSelection(Screen):
609 <screen position="140,165" size="400,130" title="select Slot">
610 <widget name="nimlist" position="20,10" size="360,100" />
613 def __init__(self, session):
614 Screen.__init__(self, session)
616 nimlist = nimmanager.getNimListOfType("DVB-S")
619 nimMenuList.append((nimmanager.nim_slots[x].friendly_full_description, x))
621 self["nimlist"] = MenuList(nimMenuList)
623 self["actions"] = ActionMap(["OkCancelActions"],
625 "ok": self.okbuttonClick ,
629 def okbuttonClick(self):
630 selection = self["nimlist"].getCurrent()
631 self.session.open(PositionerSetup, selection[1])
633 def PositionerMain(session, **kwargs):
634 nimList = nimmanager.getNimListOfType("DVB-S")
635 if len(nimList) == 0:
636 session.open(MessageBox, _("No positioner capable frontend found."), MessageBox.TYPE_ERROR)
638 if session.nav.RecordTimer.isRecording():
639 session.open(MessageBox, _("A recording is currently running. Please stop the recording before trying to configure the positioner."), MessageBox.TYPE_ERROR)
643 configured_rotor_sats = nimmanager.getRotorSatListForNim(x)
644 if len(configured_rotor_sats) != 0:
646 if len(usableNims) == 1:
647 session.open(PositionerSetup, usableNims[0])
648 elif len(usableNims) > 1:
649 session.open(RotorNimSelection)
651 session.open(MessageBox, _("No tuner is configured for use with a diseqc positioner!"), MessageBox.TYPE_ERROR)
653 def PositionerSetupStart(menuid, **kwargs):
655 return [(_("Positioner setup"), PositionerMain, "positioner_setup", None)]
659 def Plugins(**kwargs):
660 if (nimmanager.hasNimType("DVB-S")):
661 return PluginDescriptor(name=_("Positioner setup"), description="Setup your positioner", where = PluginDescriptor.WHERE_MENU, fnc=PositionerSetupStart)