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