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