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