add missing import
[vuplus_dvbapp] / lib / python / Plugins / SystemPlugins / PositionerSetup / plugin.py
1 from enigma import eTimer, eDVBSatelliteEquipmentControl, eDVBResourceManager, \
2         eDVBDiseqcCommand, eDVBFrontendParametersSatellite, eDVBFrontendParameters,\
3         iDVBFrontend
4
5 from Screens.Screen import Screen
6 from Screens.ScanSetup import ScanSetup
7 from Screens.MessageBox import MessageBox
8 from Plugins.Plugin import PluginDescriptor
9
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
17
18 from time import sleep
19
20 class PositionerSetup(Screen):
21         skin = """
22                 <screen position="100,100" size="560,400" title="Positioner setup..." >
23                         <widget name="list" position="100,0" size="350,155" />
24
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" />
29                         
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" />
41
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" />
48                 </screen>"""
49         def __init__(self, session, feid):
50                 self.skin = PositionerSetup.skin
51                 Screen.__init__(self, session)
52                 self.feid = feid
53                 self.oldref = None
54                 
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
61                                         del session.pip
62                                         if not self.openFrontend():
63                                                 self.frontend = None # in normal case this should not happen
64                                                 self.getFrontend = None
65                 
66                 self.diseqc = Diseqc(self.frontend)
67                 self.tuner = Tuner(self.frontend)
68                 self.tuner.tune((0,0,0,0,0,0))
69                 
70                 self.createConfig()
71                 
72                 self.isMoving = False
73                 self.stopOnLock = False
74                 
75                 self.red = Label("")
76                 self["red"] = self.red
77                 self.green = Label("")
78                 self["green"] = self.green
79                 self.yellow = Label("")
80                 self["yellow"] = self.yellow
81                 self.blue = Label("")
82                 self["blue"] = self.blue
83                 
84                 self.list = []
85                 self["list"] = ConfigList(self.list)
86                 self.createSetup()
87                 
88                 self["snr"] = Label()
89                 self["agc"] = Label()
90                 self["ber"] = Label()
91                 self["lock"] = Label()
92                 self["snr_percentage"] = TunerInfo(TunerInfo.SNR_PERCENTAGE, frontendfkt = self.getFrontend)
93                 self["agc_percentage"] = TunerInfo(TunerInfo.AGC_PERCENTAGE, frontendfkt = self.getFrontend)
94                 self["ber_value"] = TunerInfo(TunerInfo.BER_VALUE, frontendfkt = self.getFrontend)
95                 self["snr_bar"] = TunerInfo(TunerInfo.SNR_BAR, frontendfkt = self.getFrontend)
96                 self["agc_bar"] = TunerInfo(TunerInfo.AGC_BAR, frontendfkt = self.getFrontend)
97                 self["ber_bar"] = TunerInfo(TunerInfo.BER_BAR, frontendfkt = self.getFrontend)
98                 self["lock_state"] = TunerInfo(TunerInfo.LOCK_STATE, frontendfkt = self.getFrontend)
99
100                 self["frequency"] = Label()
101                 self["symbolrate"] = Label()
102                 self["fec"] = Label()
103
104                 self["frequency_value"] = Label("")
105                 self["symbolrate_value"] = Label("")
106                 self["fec_value"] = Label("")
107                 
108                 self["actions"] = ActionMap(["DirectionActions", "OkCancelActions", "ColorActions"],
109                 {
110                         "ok": self.go,
111                         "cancel": self.keyCancel,
112                         "up": self.up,
113                         "down": self.down,
114                         "left": self.left,
115                         "right": self.right,
116                         "red": self.redKey,
117                         "green": self.greenKey,
118                         "yellow": self.yellowKey,
119                         "blue": self.blueKey,
120                 }, -1)
121                 
122                 self.updateColors("tune")
123                 
124                 self.statusTimer = eTimer()
125                 self.statusTimer.timeout.get().append(self.updateStatus)
126                 self.statusTimer.start(50, False)
127
128         def restartPrevService(self, yesno):
129                 if yesno:
130                         if self.frontend:
131                                 self.frontend = None
132                                 del self.raw_channel
133                         self.session.nav.playService(self.oldref)
134                 self.close(None)
135         
136         def keyCancel(self):
137                 if self.oldref:
138                         self.session.openWithCallback(self.restartPrevService, MessageBox, _("Zap back to service before positioner setup?"), MessageBox.TYPE_YESNO)
139                 else:
140                         self.restartPrevService(False)
141
142         def getFrontend(self):
143                 return self.frontend
144
145         def openFrontend(self):
146                 res_mgr = eDVBResourceManager.getInstance()
147                 if res_mgr:
148                         self.raw_channel = res_mgr.allocateRawChannel(self.feid)
149                         if self.raw_channel:
150                                 self.frontend = self.raw_channel.getFrontend()
151                                 if self.frontend:
152                                         return True
153                                 else:
154                                         print "getFrontend failed"
155                         else:
156                                 print "getRawChannel failed"
157                 else:
158                         print "getResourceManager instance failed"
159                 return False
160
161         def createConfig(self):
162                 self.positioner_tune = ConfigNothing()
163                 self.positioner_move = ConfigNothing()
164                 self.positioner_finemove = ConfigNothing()
165                 self.positioner_limits = ConfigNothing()
166                 self.positioner_goto0 = ConfigNothing()
167                 storepos = []
168                 for x in range(1,255):
169                         storepos.append(str(x))
170                 self.positioner_storage = ConfigSelection(choices = storepos)
171
172         def createSetup(self):
173                 self.list.append((_("Tune"), self.positioner_tune, "tune"))
174                 self.list.append((_("Positioner movement"), self.positioner_move, "move"))
175                 self.list.append((_("Positioner fine movement"), self.positioner_finemove, "finemove"))
176                 self.list.append((_("Set limits"), self.positioner_limits, "limits"))
177                 self.list.append((_("Positioner storage"), self.positioner_storage, "storage"))
178                 self.list.append((_("Goto 0"), self.positioner_goto0, "goto0"))
179                 self["list"].l.setList(self.list)
180
181         def go(self):
182                 pass
183
184         def getCurrentConfigPath(self):
185                 return self["list"].getCurrent()[2]
186
187         def up(self):
188                 if not self.isMoving:
189                         self["list"].instance.moveSelection(self["list"].instance.moveUp)
190                         self.updateColors(self.getCurrentConfigPath())
191
192         def down(self):
193                 if not self.isMoving:
194                         self["list"].instance.moveSelection(self["list"].instance.moveDown)
195                         self.updateColors(self.getCurrentConfigPath())
196
197         def left(self):
198                 self["list"].handleKey(KEY_LEFT)
199
200         def right(self):
201                 self["list"].handleKey(KEY_RIGHT)
202
203         def updateColors(self, entry):
204                 if entry == "tune":
205                         self.red.setText(_("Tune"))
206                         self.green.setText("")
207                         self.yellow.setText("")
208                         self.blue.setText("")
209                 elif entry == "move":
210                         if self.isMoving:
211                                 self.red.setText(_("Stop"))
212                                 self.green.setText(_("Stop"))
213                                 self.yellow.setText(_("Stop"))
214                                 self.blue.setText(_("Stop"))
215                         else:
216                                 self.red.setText(_("Move west"))
217                                 self.green.setText(_("Search west"))
218                                 self.yellow.setText(_("Search east"))
219                                 self.blue.setText(_("Move east"))
220                 elif entry == "finemove":
221                         self.red.setText("")
222                         self.green.setText(_("Step west"))
223                         self.yellow.setText(_("Step east"))
224                         self.blue.setText("")
225                 elif entry == "limits":
226                         self.red.setText(_("Limits off"))
227                         self.green.setText(_("Limit west"))
228                         self.yellow.setText(_("Limit east"))
229                         self.blue.setText(_("Limits on"))
230                 elif entry == "storage":
231                         self.red.setText("")
232                         self.green.setText(_("Store position"))
233                         self.yellow.setText(_("Goto position"))
234                         self.blue.setText("")
235                 elif entry == "goto0":
236                         self.red.setText(_("Goto 0"))
237                         self.green.setText("")
238                         self.yellow.setText("")
239                         self.blue.setText("")
240                 else:
241                         self.red.setText("")
242                         self.green.setText("")
243                         self.yellow.setText("")
244                         self.blue.setText("")
245
246         def redKey(self):
247                 entry = self.getCurrentConfigPath()
248                 if entry == "move":
249                         if self.isMoving:
250                                 self.diseqccommand("stop")
251                                 self.isMoving = False
252                                 self.stopOnLock = False
253                         else:
254                                 self.diseqccommand("moveWest", 0)
255                                 self.isMoving = True
256                         self.updateColors("move")
257                 elif entry == "limits":
258                         self.diseqccommand("limitOff")
259                 elif entry == "tune":
260                         self.session.openWithCallback(self.tune, TunerScreen, self.feid)
261                 elif entry == "goto0":
262                         print "move to position 0"
263                         self.diseqccommand("moveTo", 0)
264
265         def greenKey(self):
266                 entry = self.getCurrentConfigPath()
267                 if entry == "move":
268                         if self.isMoving:
269                                 self.diseqccommand("stop")
270                                 self.isMoving = False
271                                 self.stopOnLock = False
272                         else:
273                                 self.isMoving = True
274                                 self.stopOnLock = True
275                                 self.diseqccommand("moveWest", 0)
276                         self.updateColors("move")
277                 elif entry == "finemove":
278                         print "stepping west"
279                         self.diseqccommand("moveWest", 0xFF) # one step
280                 elif entry == "storage":
281                         print "store at position", int(self.positioner_storage.value)
282                         self.diseqccommand("store", int(self.positioner_storage.value))
283                 elif entry == "limits":
284                         self.diseqccommand("limitWest")
285
286         def yellowKey(self):
287                 entry = self.getCurrentConfigPath()
288                 if entry == "move":
289                         if self.isMoving:
290                                 self.diseqccommand("stop")
291                                 self.isMoving = False
292                                 self.stopOnLock = False
293                         else:
294                                 self.isMoving = True
295                                 self.stopOnLock = True
296                                 self.diseqccommand("moveEast", 0)
297                         self.updateColors("move")
298                 elif entry == "finemove":
299                         print "stepping east"
300                         self.diseqccommand("moveEast", 0xFF) # one step
301                 elif entry == "storage":
302                         print "move to position", int(self.positioner_storage.value)
303                         self.diseqccommand("moveTo", int(self.positioner_storage.value))
304                 elif entry == "limits":
305                         self.diseqccommand("limitEast")
306
307         def blueKey(self):
308                 entry = self.getCurrentConfigPath()
309                 if entry == "move":
310                         if self.isMoving:
311                                 self.diseqccommand("stop")
312                                 self.isMoving = False
313                                 self.stopOnLock = False
314                         else:
315                                 self.diseqccommand("moveEast", 0)
316                                 self.isMoving = True
317                         self.updateColors("move")
318                         print "moving east"
319                 elif entry == "limits":
320                         self.diseqccommand("limitOn")
321
322         def diseqccommand(self, cmd, param = 0):
323                 self.diseqc.command(cmd, param)
324                 self.tuner.retune()
325
326         def updateStatus(self):
327                 self["snr_percentage"].update()
328                 self["agc_percentage"].update()
329                 self["ber_value"].update()
330                 self["snr_bar"].update()
331                 self["agc_bar"].update()
332                 self["ber_bar"].update()
333                 self["lock_state"].update()
334                 transponderdata = self.tuner.getTransponderData()
335                 self["frequency_value"].setText(str(transponderdata["frequency"]))
336                 self["symbolrate_value"].setText(str(transponderdata["symbol_rate"]))
337                 self["fec_value"].setText(str(transponderdata["fec_inner"]))
338                 if transponderdata["tuner_locked"] == 1 and self.isMoving and self.stopOnLock:
339                         self.diseqccommand("stop")
340                         self.isMoving = False
341                         self.stopOnLock = False
342                         self.updateColors(self.getCurrentConfigPath())
343
344         def tune(self, transponder):
345                 if transponder is not None:
346                         self.tuner.tune(transponder)
347
348 class Diseqc:
349         def __init__(self, frontend):
350                 self.frontend = frontend
351
352         def command(self, what, param = 0):
353                 if self.frontend:
354                         cmd = eDVBDiseqcCommand()
355                         if what == "moveWest":
356                                 string = 'e03169' + ("%02x" % param)
357                         elif what == "moveEast":
358                                 string = 'e03168' + ("%02x" % param)
359                         elif what == "moveTo":
360                                 string = 'e0316b' + ("%02x" % param)
361                         elif what == "store":
362                                 string = 'e0316a' + ("%02x" % param)
363                         elif what == "limitOn":
364                                 string = 'e0316a00'
365                         elif what == "limitOff":
366                                 string = 'e03163'
367                         elif what == "limitEast":
368                                 string = 'e03166'
369                         elif what == "limitWest":
370                                 string = 'e03167'
371                         else:
372                                 string = 'e03160' #positioner stop
373                         
374                         print "diseqc command:",
375                         print string
376                         cmd.setCommandString(string)
377                         self.frontend.setTone(iDVBFrontend.toneOff)
378                         sleep(0.015) # wait 15msec after disable tone
379                         self.frontend.sendDiseqc(cmd)
380                         if string == 'e03160': #positioner stop
381                                 sleep(0.05)
382                                 self.frontend.sendDiseqc(cmd) # send 2nd time
383
384 class Tuner:
385         def __init__(self, frontend):
386                 self.frontend = frontend
387
388         def tune(self, transponder):
389                 print "tuning to transponder with data", transponder
390                 parm = eDVBFrontendParametersSatellite()
391                 parm.frequency = transponder[0] * 1000
392                 parm.symbol_rate = transponder[1] * 1000
393                 parm.polarisation = transponder[2]
394                 parm.fec = transponder[3]
395                 parm.inversion = transponder[4]
396                 parm.orbital_position = transponder[5]
397                 parm.system = 0  # FIXMEE !! HARDCODED DVB-S (add support for DVB-S2)
398                 parm.modulation = 1 # FIXMEE !! HARDCODED QPSK
399                 feparm = eDVBFrontendParameters()
400                 feparm.setDVBS(parm, True)
401                 self.lastparm = feparm
402                 if self.frontend:
403                         self.frontend.tune(feparm)
404
405         def retune(self):
406                 if self.frontend:
407                         self.frontend.tune(self.lastparm)
408
409         def getTransponderData(self):
410                 if self.frontend:
411                         return self.frontend.readTransponderData(True)
412                 return None
413
414 tuning = None
415
416 class TunerScreen(ScanSetup):
417         skin = """
418                 <screen position="90,100" size="520,400" title="Tune">
419                         <widget name="config" position="20,10" size="460,350" scrollbarMode="showOnDemand" />
420                         <widget name="introduction" position="20,360" size="350,30" font="Regular;23" />
421                 </screen>"""
422
423         def __init__(self, session, feid):
424                 self.feid = feid
425                 ScanSetup.__init__(self, session)
426                 self["introduction"].setText("")
427
428         def createSetup(self):
429                 self.typeOfTuningEntry = None
430                 self.satEntry = None
431                 self.list = []
432                 self.typeOfTuningEntry = getConfigListEntry(_('Tune'), tuning.type)
433                 self.list.append(self.typeOfTuningEntry)
434                 self.satEntry = getConfigListEntry(_('Satellite'), tuning.sat)
435                 self.list.append(self.satEntry)
436                 if tuning.type.value == "manual_transponder":
437                         self.list.append(getConfigListEntry(_('Frequency'), self.scan_sat.frequency))
438                         self.list.append(getConfigListEntry(_('Inversion'), self.scan_sat.inversion))
439                         self.list.append(getConfigListEntry(_('Symbol Rate'), self.scan_sat.symbolrate))
440                         self.list.append(getConfigListEntry(_("Polarity"), self.scan_sat.polarization))
441                         self.list.append(getConfigListEntry(_("FEC"), self.scan_sat.fec))
442                 elif tuning.type.value == "predefined_transponder":
443                         self.list.append(getConfigListEntry(_("Transponder"), tuning.transponder))
444                 self["config"].list = self.list
445                 self["config"].l.setList(self.list)
446
447         def newConfig(self):
448                 if self["config"].getCurrent() == self.typeOfTuningEntry:
449                         self.createSetup()
450                 elif self["config"].getCurrent() == self.satEntry:
451                         self.createSetup()
452
453         def createConfig(self, foo):
454                 global tuning
455                 if not tuning:
456                         tuning = ConfigSubsection()
457                         tuning.type = ConfigSelection(
458                                 default = "manual_transponder",
459                                 choices = { "manual_transponder" : _("Manual transponder"),
460                                                         "predefined_transponder" : _("Predefined transponder") } )
461                         tuning.sat = ConfigSatlist(list=nimmanager.getRotorSatListForNim(self.feid))
462                         tuning.sat.addNotifier(self.tuningSatChanged)
463                         self.updateTransponders()
464                         TunerScreenConfigCreated = True
465                 ScanSetup.createConfig(self, None)
466
467         def tuningSatChanged(self, *parm):
468                 self.updateTransponders()
469
470         def updateTransponders(self):
471                 if len(tuning.sat.choices):
472                         transponderlist = nimmanager.getTransponders(int(tuning.sat.value))
473                         tps = []
474                         cnt=0
475                         for x in transponderlist:
476                                 if x[3] == 0:
477                                         pol = "H"
478                                 elif x[3] == 1:
479                                         pol = "V"
480                                 elif x[3] == 2:
481                                         pol = "CL"
482                                 elif x[3] == 3:
483                                         pol = "CR"
484                                 if x[4] == 0:
485                                         fec = "FEC_AUTO"
486                                 elif x[4] == 1:
487                                         fec = "FEC_1_2"
488                                 elif x[4] == 2:
489                                         fec = "FEC_2_3"
490                                 elif x[4] == 3:
491                                         fec = "FEC_3_4"
492                                 elif x[4] == 4:
493                                         fec = "FEC_5_6"
494                                 elif x[4] == 5:
495                                         fec = "FEC_7_8"
496                                 elif x[4] == 5:
497                                         fec = "FEC_8_9"
498                                 elif x[4] == 6:
499                                         fec = "FEC_None"
500                                 tps.append(str(x[1]) + "," + str(x[2]) + "," + pol + "," + fec)
501                         tuning.transponder = ConfigSelection(choices=tps)
502
503         def keyGo(self):
504                 returnvalue = (0, 0, 0, 0, 0, 0)
505                 satpos = int(tuning.sat.value)
506                 if tuning.type.value == "manual_transponder":
507                         returnvalue = (
508                                 self.scan_sat.frequency.value,
509                                 self.scan_sat.symbolrate.value,
510                                 self.scan_sat.polarization.index,
511                                 self.scan_sat.fec.index,
512                                 self.scan_sat.inversion.index,
513                                 satpos)
514                 elif tuning.type.value == "predefined_transponder":
515                         transponder = nimmanager.getTransponders(satpos)[tuning.transponder.index]
516                         returnvalue = (int(transponder[1] / 1000), int(transponder[2] / 1000), transponder[3], transponder[4], 2, satpos)
517                 self.close(returnvalue)
518
519         def keyCancel(self):
520                 self.close(None)
521
522 class NimSelection(Screen):
523         skin = """
524                 <screen position="140,165" size="400,100" title="select Slot">
525                         <widget name="nimlist" position="20,10" size="360,75" />
526                 </screen>"""
527
528         def __init__(self, session):
529                 Screen.__init__(self, session)
530
531                 nimlist = nimmanager.getNimListOfType(nimmanager.nimType["DVB-S"])
532                 nimMenuList = []
533                 for x in nimlist:
534                         nimMenuList.append((_("NIM ") + (["A", "B", "C", "D"][x]) + ": " + nimmanager.getNimName(x) + " (" + nimmanager.getNimTypeName(x) + ")", x))
535                 
536                 self["nimlist"] = MenuList(nimMenuList)
537
538                 self["actions"] = ActionMap(["OkCancelActions"],
539                 {
540                         "ok": self.okbuttonClick ,
541                         "cancel": self.close
542                 }, -1)
543
544         def okbuttonClick(self):
545                 selection = self["nimlist"].getCurrent()
546                 self.session.open(PositionerSetup, selection[1])
547
548 def PositionerMain(session, **kwargs):
549         nimList = nimmanager.getNimListOfType(nimmanager.nimType["DVB-S"])
550         if len(nimList) == 0:
551                 session.open(MessageBox, _("No positioner capable frontend found."), MessageBox.TYPE_ERROR)
552         else:
553                 if session.nav.RecordTimer.isRecording():
554                         session.open(MessageBox, _("A recording is currently running. Please stop the recording before trying to configure the positioner."), MessageBox.TYPE_ERROR)
555                 else:
556                         usableNims = []
557                         for x in nimList:
558                                 configured_rotor_sats = nimmanager.getRotorSatListForNim(x)
559                                 if len(configured_rotor_sats) != 0:
560                                         usableNims.append(x)
561                         if len(usableNims) == 1:
562                                 session.open(PositionerSetup, usableNims[0])
563                         elif len(usableNims) > 1:
564                                 session.open(NimSelection)
565                         else:
566                                 session.open(MessageBox, _("No tuner is configured for use with a diseqc positioner!"), MessageBox.TYPE_ERROR)
567
568 def PositionerSetupStart(menuid):
569         if menuid == "scan":
570                 return [(_("Positioner setup"), PositionerMain)]
571         else:
572                 return []
573
574 def Plugins(**kwargs):
575         return PluginDescriptor(name=_("Positioner setup"), description="Setup your positioner", where = PluginDescriptor.WHERE_SETUP, fnc=PositionerSetupStart)