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