count indexes instead of transponders for failed/successfully tuned indexes
[vuplus_dvbapp] / lib / python / Plugins / SystemPlugins / DiseqcTester / plugin.py
1 from Screens.Satconfig import NimSelection
2 from Screens.Screen import Screen
3 from Screens.TextBox import TextBox
4 from Screens.MessageBox import MessageBox
5
6 from Plugins.Plugin import PluginDescriptor
7
8 from Components.ActionMap import ActionMap, NumberActionMap
9 from Components.NimManager import nimmanager
10 from Components.ResourceManager import resourcemanager
11 from Components.Sources.FrontendStatus import FrontendStatus
12 from Components.TuneTest import TuneTest
13 from Components.Sources.List import List
14 from Components.Sources.Progress import Progress
15 from Components.Sources.StaticText import StaticText
16 from Components.ConfigList import ConfigListScreen
17 from Components.config import getConfigListEntry, ConfigSelection, ConfigYesNo
18 from Components.Harddisk import harddiskmanager
19
20 import random
21
22 # always use:
23 # setResultType(type)
24 # setResultParameter(parameter)
25 # getTextualResult()
26 class ResultParser:
27         def __init__(self):
28                 pass
29         
30         TYPE_BYORBPOS = 0
31         TYPE_BYINDEX = 1
32         TYPE_ALL = 2
33         def setResultType(self, type):
34                 self.type = type
35                 
36         def setResultParameter(self, parameter):
37                 if self.type == self.TYPE_BYORBPOS:
38                         self.orbpos = parameter
39                 elif self.type == self.TYPE_BYINDEX:
40                         self.index = parameter
41                         
42         def getTextualResultForIndex(self, index, logfulltransponders = False):
43                 text = ""
44                 text += "%s:\n" % self.getTextualIndexRepresentation(index)
45                 
46                 failed, successful = self.results[index]["failed"], self.results[index]["successful"]
47                 countfailed = len(failed)
48                 countsuccessful = len(successful)
49                 countall = countfailed + countsuccessful
50                 percentfailed = round(countfailed / float(countall + 0.0001) * 100)
51                 percentsuccessful = round(countsuccessful / float(countall + 0.0001) * 100)
52                 text += "Tested %d transponders\n%d (%d %%) transponders succeeded\n%d (%d %%) transponders failed\n" % (countall, countsuccessful, percentsuccessful, countfailed, percentfailed)
53                 reasons = {}
54                 if countfailed > 0:
55                         for transponder in failed:
56                                 reasons[transponder[2]] = reasons.get(transponder[2], [])
57                                 reasons[transponder[2]].append(transponder)
58                                 if transponder[2] == "pids_failed":
59                                         print transponder[2], "-", transponder[3]
60                                 
61                         text += "The %d unsuccessful tuning attempts failed for the following reasons:\n" % countfailed
62                         
63                         for reason in reasons.keys():
64                                 text += "%s: %d transponders failed\n" % (reason, len(reasons[reason]))
65                         
66                         for reason in reasons.keys():
67                                 text += "\n"
68                                 text += "%s previous planes:\n" % reason
69                                 for transponder in reasons[reason]:
70                                         if transponder[1] is not None:
71                                                 text += self.getTextualIndexRepresentation(self.getIndexForTransponder(transponder[1]))
72                                         else:
73                                                 text += "No transponder tuned"
74                                         text += " ==> " + self.getTextualIndexRepresentation(self.getIndexForTransponder(transponder[0]))
75                                         text += "\n"
76                                         if logfulltransponders:
77                                                 text += str(transponder[1])
78                                                 text += " ==> "
79                                                 text += str(transponder[0])
80                                                 text += "\n"
81                 if countsuccessful > 0:
82                         text += "\n"
83                         text += "Successfully tuned transponders' previous planes:\n" 
84                         for transponder in successful:
85                                 if transponder[1] is not None:
86                                         text += self.getTextualIndexRepresentation(self.getIndexForTransponder(transponder[1]))
87                                 else:
88                                         text += "No transponder tuned"
89                                 text += " ==> " + self.getTextualIndexRepresentation(self.getIndexForTransponder(transponder[0]))
90                                 text += "\n"
91                 return text
92
93         def getTextualResult(self):
94                 text = ""
95                 if self.type == self.TYPE_BYINDEX:
96                         text += self.getTextualResultForIndex(self.index)
97                 elif self.type == self.TYPE_BYORBPOS:
98                         for index in self.results.keys():
99                                 if index[2] == self.orbpos:
100                                         text += self.getTextualResultForIndex(index)
101                                         text += "\n-----------------------------------------------------\n"
102                 elif self.type == self.TYPE_ALL:
103                         orderedResults = {}
104                         for index in self.results.keys():
105                                 orbpos = index[2]
106                                 orderedResults[orbpos] = orderedResults.get(orbpos, [])
107                                 orderedResults[orbpos].append(index)
108                         ordered_orbpos = orderedResults.keys()
109                         ordered_orbpos.sort()
110                         for orbpos in ordered_orbpos:
111                                 text += "\n*****************************************\n"
112                                 text += "Orbital position %s:" % str(orbpos)
113                                 text += "\n*****************************************\n"
114                                 for index in orderedResults[orbpos]:
115                                         text += self.getTextualResultForIndex(index, logfulltransponders = True)
116                                         text += "\n-----------------------------------------------------\n"
117                         
118                                 
119                 return text
120
121 class DiseqcTester(Screen, TuneTest, ResultParser):
122         skin = """
123                 <screen position="90,100" size="520,400" title="DiSEqC Tester" >
124                 <!--ePixmap pixmap="skin_default/icons/dish_scan.png" position="5,25" zPosition="0" size="119,110" transparent="1" alphatest="on" />
125                 <widget source="Frontend" render="Label" position="190,10" zPosition="2" size="260,20" font="Regular;19" halign="center" valign="center" transparent="1">
126                         <convert type="FrontendInfo">SNRdB</convert>
127                 </widget>
128                 <eLabel name="snr" text="SNR:" position="120,35" size="60,22" font="Regular;21" halign="right" transparent="1" />
129                 <widget source="Frontend" render="Progress" position="190,35" size="260,20" pixmap="skin_default/bar_snr.png" borderWidth="2" borderColor="#cccccc">
130                         <convert type="FrontendInfo">SNR</convert>
131                 </widget>
132                 <widget source="Frontend" render="Label" position="460,35" size="60,22" font="Regular;21">
133                         <convert type="FrontendInfo">SNR</convert>
134                 </widget>
135                 <eLabel name="agc" text="AGC:" position="120,60" size="60,22" font="Regular;21" halign="right" transparent="1" />
136                 <widget source="Frontend" render="Progress" position="190,60" size="260,20" pixmap="skin_default/bar_snr.png" borderWidth="2" borderColor="#cccccc">
137                         <convert type="FrontendInfo">AGC</convert>
138                 </widget>
139                 <widget source="Frontend" render="Label" position="460,60" size="60,22" font="Regular;21">
140                         <convert type="FrontendInfo">AGC</convert>
141                 </widget>
142                 <eLabel name="ber" text="BER:" position="120,85" size="60,22" font="Regular;21" halign="right" transparent="1" />
143                 <widget source="Frontend" render="Progress" position="190,85" size="260,20" pixmap="skin_default/bar_ber.png" borderWidth="2" borderColor="#cccccc">
144                         <convert type="FrontendInfo">BER</convert>
145                 </widget>
146                 <widget source="Frontend" render="Label" position="460,85" size="60,22" font="Regular;21">
147                         <convert type="FrontendInfo">BER</convert>
148                 </widget>
149                 <eLabel name="lock" text="Lock:" position="120,115" size="60,22" font="Regular;21" halign="right" />
150                 <widget source="Frontend" render="Pixmap" pixmap="skin_default/icons/lock_on.png" position="190,110" zPosition="1" size="38,31" alphatest="on">
151                         <convert type="FrontendInfo">LOCK</convert>
152                         <convert type="ConditionalShowHide" />
153                 </widget>
154                 <widget source="Frontend" render="Pixmap" pixmap="skin_default/icons/lock_off.png" position="190,110" zPosition="1" size="38,31" alphatest="on">
155                         <convert type="FrontendInfo">LOCK</convert>
156                         <convert type="ConditionalShowHide">Invert</convert>
157                 </widget-->
158                 <widget source="progress_list" render="Listbox" position="0,0" size="510,150" scrollbarMode="showOnDemand">
159                         <convert type="TemplatedMultiContent">
160                                 {"template": [
161                                                 MultiContentEntryText(pos = (10, 0), size = (330, 25), flags = RT_HALIGN_LEFT, text = 1), # index 1 is the index name,
162                                                 MultiContentEntryText(pos = (330, 0), size = (150, 25), flags = RT_HALIGN_RIGHT, text = 2) # index 2 is the status,
163                                         ],
164                                  "fonts": [gFont("Regular", 20)],
165                                  "itemHeight": 25
166                                 }
167                         </convert>
168                 </widget>
169                 <eLabel name="overall_progress" text="Overall progress:" position="20,162" size="480,22" font="Regular;21" halign="center" transparent="1" />
170                 <widget source="overall_progress" render="Progress" position="20,192" size="480,20" borderWidth="2" backgroundColor="#254f7497" />
171                 <eLabel name="overall_progress" text="Progress:" position="20,222" size="480,22" font="Regular;21" halign="center" transparent="1" />
172                 <widget source="sub_progress" render="Progress" position="20,252" size="480,20" borderWidth="2" backgroundColor="#254f7497" />
173                 
174                 <eLabel name="" text="Failed:" position="20,282" size="140,22" font="Regular;21" halign="left" transparent="1" />
175                 <widget source="failed_counter" render="Label" position="160,282" size="100,20" font="Regular;21" />
176                 
177                 <eLabel name="" text="Succeeded:" position="20,312" size="140,22" font="Regular;21" halign="left" transparent="1" />
178                 <widget source="succeeded_counter" render="Label" position="160,312" size="100,20" font="Regular;21" />
179                 
180                 <eLabel name="" text="With errors:" position="20,342" size="140,22" font="Regular;21" halign="left" transparent="1" />
181                 <widget source="witherrors_counter" render="Label" position="160,342" size="100,20" font="Regular;21" />
182                 
183                 <eLabel name="" text="Not tested:" position="20,372" size="140,22" font="Regular;21" halign="left" transparent="1" />
184                 <widget source="untestable_counter" render="Label" position="160,372" size="100,20" font="Regular;21" />
185                 
186                 <widget source="CmdText" render="Label" position="300,282" size="180,200" font="Regular;21" />
187                 </screen>"""
188                 
189         TEST_TYPE_QUICK = 0
190         TEST_TYPE_RANDOM = 1
191         TEST_TYPE_COMPLETE = 2
192         def __init__(self, session, feid, test_type = TEST_TYPE_QUICK, loopsfailed = 3, loopssuccessful = 1, log = False):
193                 Screen.__init__(self, session)
194                 self.feid = feid
195                 self.test_type = test_type
196                 self.loopsfailed = loopsfailed
197                 self.loopssuccessful = loopssuccessful
198                 self.log = log
199                 
200                 self["actions"] = NumberActionMap(["SetupActions"],
201                 {
202                         "ok": self.select,
203                         "cancel": self.keyCancel,
204                 }, -2)
205                 
206                 TuneTest.__init__(self, feid, stopOnSuccess = self.loopssuccessful, stopOnError = self.loopsfailed)
207                 #self["Frontend"] = FrontendStatus(frontend_source = lambda : self.frontend, update_interval = 100)
208                 self["overall_progress"] = Progress()
209                 self["sub_progress"] = Progress()
210                 
211                 self["failed_counter"] = StaticText("0")
212                 self["succeeded_counter"] = StaticText("0")
213                 self["witherrors_counter"] = StaticText("0")
214                 self["untestable_counter"] = StaticText("0")
215                 
216                 self.list = []
217                 self["progress_list"] = List(self.list)
218                 self["progress_list"].onSelectionChanged.append(self.selectionChanged)
219                 
220                 self["CmdText"] = StaticText(_("Please wait while scanning is in progress..."))
221                                 
222                 self.indexlist = {}
223                 self.readTransponderList()
224                 
225                 self.running = False
226                 
227                 self.results = {}
228                 self.resultsstatus = {}
229                 
230                 self.onLayoutFinish.append(self.go)
231                 
232         def getProgressListComponent(self, index, status):
233                 return (index, self.getTextualIndexRepresentation(index), status)
234         
235         def clearProgressList(self):
236                 self.list = []
237                 self["progress_list"].list = self.list
238         
239         def addProgressListItem(self, index):
240                 if index in self.indexlist:
241                         for entry in self.list:
242                                 if entry[0] == index:
243                                         self.changeProgressListStatus(index, "working")
244                                         return
245                         self.list.append(self.getProgressListComponent(index, _("working")))
246                         self["progress_list"].list = self.list
247                         self["progress_list"].setIndex(len(self.list) - 1)
248
249         def changeProgressListStatus(self, index, status):
250                 self.newlist = []
251                 count = 0
252                 indexpos = 0
253                 for entry in self.list:
254                         if entry[0] == index:
255                                 self.newlist.append(self.getProgressListComponent(index, status))
256                                 indexpos = count
257                         else:
258                                 self.newlist.append(entry)
259                         count += 1
260                 self.list = self.newlist
261                 self["progress_list"].list = self.list
262                 self["progress_list"].setIndex(indexpos)
263
264         def readTransponderList(self):
265                 for sat in nimmanager.getSatListForNim(self.feid):
266                         for transponder in nimmanager.getTransponders(sat[0]):
267                                 #print transponder
268                                 mytransponder = (transponder[1] / 1000, transponder[2] / 1000, transponder[3], transponder[4], transponder[5], sat[0], None, None, transponder[10], transponder[11])
269                                 self.analyseTransponder(mytransponder)
270
271         def getIndexForTransponder(self, transponder):
272                 
273                 if transponder[0] < 11700:
274                         band = 1 # low
275                 else:
276                         band = 0 # high
277                 
278                 polarisation = transponder[2]
279                 
280                 sat = transponder[5]
281                 
282                 index = (band, polarisation, sat)
283                 return index
284
285         # sort the transponder into self.transponderlist
286         def analyseTransponder(self, transponder):
287                 index = self.getIndexForTransponder(transponder)
288                 if index not in self.indexlist:
289                         self.indexlist[index] = []
290                 self.indexlist[index].append(transponder)
291                 #print "self.indexlist:", self.indexlist
292         
293         # returns a string for the user representing a human readable output for index 
294         def getTextualIndexRepresentation(self, index):
295                 print "getTextualIndexRepresentation:", index
296                 text = ""
297                 
298                 text += nimmanager.getSatDescription(index[2]) + ", "
299                 
300                 if index[0] == 1:
301                         text += "Low Band, "
302                 else:
303                         text += "High Band, "
304                         
305                 if index[1] == 0:
306                         text += "H"
307                 else:
308                         text += "V"
309                 return text
310         
311         def fillTransponderList(self):
312                 self.clearTransponder()
313                 print "----------- fillTransponderList"
314                 print "index:", self.currentlyTestedIndex
315                 keys = self.indexlist.keys()
316                 if self.getContinueScanning():
317                         print "index:", self.getTextualIndexRepresentation(self.currentlyTestedIndex)
318                         for transponder in self.indexlist[self.currentlyTestedIndex]:
319                                 self.addTransponder(transponder)
320                         print "transponderList:", self.transponderlist
321                         return True
322                 else:
323                         return False
324                 
325         def progressCallback(self, progress):
326                 if progress[0] != self["sub_progress"].getRange():
327                         self["sub_progress"].setRange(progress[0])
328                 self["sub_progress"].setValue(progress[1])
329
330         # logic for scanning order of transponders
331         # on go getFirstIndex is called
332         def getFirstIndex(self):
333                 # TODO use other function to scan more randomly
334                 if self.test_type == self.TEST_TYPE_QUICK:
335                         self.myindex = 0
336                         keys = self.indexlist.keys()
337                         keys.sort(key = lambda a: a[2]) # sort by orbpos
338                         self["overall_progress"].setRange(len(keys))
339                         self["overall_progress"].setValue(self.myindex)
340                         return keys[0]
341                 elif self.test_type == self.TEST_TYPE_RANDOM:
342                         self.randomkeys = self.indexlist.keys()
343                         random.shuffle(self.randomkeys)
344                         self.myindex = 0
345                         self["overall_progress"].setRange(len(self.randomkeys))
346                         self["overall_progress"].setValue(self.myindex)
347                         return self.randomkeys[0]
348                 
349         # after each index is finished, getNextIndex is called to get the next index to scan 
350         def getNextIndex(self):
351                 # TODO use other function to scan more randomly
352                 if self.test_type == self.TEST_TYPE_QUICK:
353                         self.myindex += 1
354                         keys = self.indexlist.keys()
355                         keys.sort(key = lambda a: a[2]) # sort by orbpos
356                         
357                         self["overall_progress"].setValue(self.myindex)
358                         if self.myindex < len(keys):
359                                 return keys[self.myindex]
360                         else:
361                                 return None
362                 elif self.test_type == self.TEST_TYPE_RANDOM:
363                         self.myindex += 1
364                         keys = self.randomkeys
365                         
366                         self["overall_progress"].setValue(self.myindex)
367                         if self.myindex < len(keys):
368                                 return keys[self.myindex]
369                         else:
370                                 return None
371                                 
372         # after each index is finished and the next index is returned by getNextIndex
373         # the algorithm checks, if we should continue scanning
374         def getContinueScanning(self):
375                 if self.test_type == self.TEST_TYPE_QUICK or self.test_type == self.TEST_TYPE_RANDOM:
376                         return (self.myindex < len(self.indexlist.keys()))
377                 
378         def addResult(self, index, status, failedTune, successfullyTune):
379                 self.results[index] = self.results.get(index, {"failed": [], "successful": [], "status": None})
380                 self.resultsstatus[status] = self.resultsstatus.get(status, [])
381                 
382                 self.results[index]["status"] = status
383                 self.results[index]["failed"] = failedTune
384                 self.results[index]["successful"] = successfullyTune
385                 
386                 self.resultsstatus[status].append(index)
387         
388         def finishedChecking(self):
389                 print "finishedChecking"
390                 TuneTest.finishedChecking(self)
391
392                 if not self.results.has_key(self.currentlyTestedIndex):
393                         self.results[self.currentlyTestedIndex] = {"failed": [], "successful": [], "status": None}
394                 
395                 if len(self.failedTune) > 0 and len(self.successfullyTune) > 0:
396                         self.changeProgressListStatus(self.currentlyTestedIndex, "with errors")
397                         self["witherrors_counter"].setText(str(int(self["witherrors_counter"].getText()) + 1))
398                         self.addResult(self.currentlyTestedIndex, "with_errors", self.failedTune, self.successfullyTune)
399                 elif len(self.failedTune) == 0 and len(self.successfullyTune) == 0:
400                         self.changeProgressListStatus(self.currentlyTestedIndex, "not tested")
401                         self["untestable_counter"].setText(str(int(self["untestable_counter"].getText()) + 1))
402                         self.addResult(self.currentlyTestedIndex, "untestable", self.failedTune, self.successfullyTune)
403                 elif len(self.failedTune) > 0:
404                         self.changeProgressListStatus(self.currentlyTestedIndex, "failed")
405                         #self["failed_counter"].setText(str(int(self["failed_counter"].getText()) + len(self.failedTune)))
406                         self["failed_counter"].setText(str(int(self["failed_counter"].getText()) + 1))
407                         self.addResult(self.currentlyTestedIndex, "failed", self.failedTune, self.successfullyTune)
408                 else:
409                         self.changeProgressListStatus(self.currentlyTestedIndex, "successful")
410                         #self["succeeded_counter"].setText(str(int(self["succeeded_counter"].getText()) + len(self.successfullyTune)))
411                         self["succeeded_counter"].setText(str(int(self["succeeded_counter"].getText()) + 1))
412                         self.addResult(self.currentlyTestedIndex, "successful", self.failedTune, self.successfullyTune)
413                         
414                         
415                 #self["failed_counter"].setText(str(int(self["failed_counter"].getText()) + len(self.failedTune)))
416                 #self["succeeded_counter"].setText(str(int(self["succeeded_counter"].getText()) + len(self.successfullyTune)))
417                 #if len(self.failedTune) == 0 and len(self.successfullyTune) == 0:
418                         #self["untestable_counter"].setText(str(int(self["untestable_counter"].getText()) + 1))
419                         
420                 self.currentlyTestedIndex = self.getNextIndex()
421                 self.addProgressListItem(self.currentlyTestedIndex)
422                 
423                 if self.fillTransponderList():
424                         self.run(checkPIDs = True)
425                 else:
426                         self.running = False
427                         self["progress_list"].setIndex(0)
428                         print "results:", self.results
429                         print "resultsstatus:", self.resultsstatus
430                         if self.log:
431                                 file = open("/media/hdd/diseqctester.log", "w")
432                                 self.setResultType(ResultParser.TYPE_ALL)
433                                 file.write(self.getTextualResult())
434                                 file.close()
435                                 self.session.open(MessageBox, text=_("The results have been written to %s.") % "/media/hdd/diseqctester.log", type = MessageBox.TYPE_INFO)
436
437         def go(self):
438                 self.running = True
439                 self["failed_counter"].setText("0")
440                 self["succeeded_counter"].setText("0")
441                 self["untestable_counter"].setText("0")
442                 self.currentlyTestedIndex = self.getFirstIndex()
443                 
444                 self.clearProgressList()
445                 self.addProgressListItem(self.currentlyTestedIndex)
446                 
447                 if self.fillTransponderList():
448                         self.run(True)
449
450         def keyCancel(self):
451                 self.close()
452                 
453         def select(self):
454                 print "selectedIndex:", self["progress_list"].getCurrent()[0]
455                 if not self.running:
456                         index = self["progress_list"].getCurrent()[0]
457                         #self.setResultType(ResultParser.TYPE_BYORBPOS)
458                         #self.setResultParameter(index[2])
459                         self.setResultType(ResultParser.TYPE_BYINDEX)
460                         self.setResultParameter(index)
461                         #self.setResultType(ResultParser.TYPE_ALL)
462                         self.session.open(TextBox, self.getTextualResult())
463         
464         def selectionChanged(self):
465                 print "selection changed"
466                 if len(self.list) > 0 and not self.running:
467                         self["CmdText"].setText(_("Press OK to get further details for %s") % str(self["progress_list"].getCurrent()[1]))
468
469 class DiseqcTesterTestTypeSelection(Screen, ConfigListScreen):
470         skin = """<screen position="80,95" size="560,412" title="DiSEqC Tester Test Settings">
471                 <widget name="config" position="10,10" size="540,402" scrollbarMode="showOnDemand" />
472         </screen>
473         """
474         def __init__(self, session, feid):
475                 Screen.__init__(self, session)
476                 self.feid = feid
477                 
478                 self.list = []
479                 ConfigListScreen.__init__(self, self.list)
480                 
481                 self["actions"] = ActionMap(["SetupActions"],
482                 {
483                         "cancel": self.keyCancel
484                 }, -2)
485                 
486                 self.createSetup()
487                 
488         def createSetup(self):
489                 self.testtype = ConfigSelection(choices={"quick": _("Quick"), "random": _("Random")}, default = "quick")
490                 self.testtypeEntry = getConfigListEntry(_("Test Type"), self.testtype)
491                 self.list.append(self.testtypeEntry)
492                 
493                 self.loopsfailed = ConfigSelection(choices={"-1": "Every known", "1": "1", "2": "2", "3": "3", "4": "4", "5": "5", "6": "6", "7": "7", "8": "8"}, default = "3")
494                 self.loopsfailedEntry = getConfigListEntry(_("Stop testing plane after # failed transponders"), self.loopsfailed)
495                 self.list.append(self.loopsfailedEntry)
496                 
497                 self.loopssuccessful = ConfigSelection(choices={"-1": "Every known", "1": "1", "2": "2", "3": "3", "4": "4", "5": "5", "6": "6", "7": "7", "8": "8"}, default = "1")
498                 self.loopssuccessfulEntry = getConfigListEntry(_("Stop testing plane after # successful transponders"), self.loopssuccessful)
499                 self.list.append(self.loopssuccessfulEntry)
500                 
501                 self.log = ConfigYesNo(False)
502                 if harddiskmanager.HDDCount() > 0:
503                         self.logEntry = getConfigListEntry(_("Log results to harddisk"), self.log)
504                         self.list.append(self.logEntry)
505                                         
506                 self["config"].list = self.list
507                 self["config"].l.setList(self.list)
508                 
509         def keyOK(self):
510                 print self.testtype.getValue()
511                 testtype = DiseqcTester.TEST_TYPE_QUICK
512                 if self.testtype.getValue() == "quick":
513                         testtype = DiseqcTester.TEST_TYPE_QUICK
514                 elif self.testtype.getValue() == "random":
515                         testtype = DiseqcTester.TEST_TYPE_RANDOM
516                 elif self.testtype.getValue() == "complete":
517                         testtype = DiseqcTester.TEST_TYPE_COMPLETE
518                 self.session.open(DiseqcTester, feid = self.feid, test_type = testtype, loopsfailed = int(self.loopsfailed.value), loopssuccessful = int(self.loopssuccessful.value), log = self.log.value)
519         
520         def keyCancel(self):
521                 self.close()
522
523 class DiseqcTesterNimSelection(NimSelection):
524         skin = """
525                 <screen position="160,123" size="400,330" title="Choose Tuner">
526                 <widget source="nimlist" render="Listbox" position="0,0" size="380,300" scrollbarMode="showOnDemand">
527                         <convert type="TemplatedMultiContent">
528                                 {"template": [
529                                                 MultiContentEntryText(pos = (10, 5), size = (360, 30), flags = RT_HALIGN_LEFT, text = 1), # index 1 is the nim name,
530                                                 MultiContentEntryText(pos = (50, 30), size = (320, 30), font = 1, flags = RT_HALIGN_LEFT, text = 2), # index 2 is a description of the nim settings,
531                                         ],
532                                  "fonts": [gFont("Regular", 20), gFont("Regular", 15)],
533                                  "itemHeight": 70
534                                 }
535                         </convert>
536                 </widget>
537         </screen>"""
538                 
539         def __init__(self, session, args = None):
540                 NimSelection.__init__(self, session)
541
542         def setResultClass(self):
543                 #self.resultclass = DiseqcTester
544                 self.resultclass = DiseqcTesterTestTypeSelection
545                 
546         def showNim(self, nim):
547                 nimConfig = nimmanager.getNimConfig(nim.slot)
548                 if nim.isCompatible("DVB-S"):
549                         if nimConfig.configMode.value in ["loopthrough", "equal", "satposdepends", "nothing"]:
550                                 return False
551                         if nimConfig.configMode.value == "simple":
552                                 if nimConfig.diseqcMode.value == "positioner":
553                                         return True
554                         return True
555                 return False
556
557 def DiseqcTesterMain(session, **kwargs):
558         session.open(DiseqcTesterNimSelection)
559         
560 def autostart(reason, **kwargs):
561         resourcemanager.addResource("DiseqcTester", DiseqcTesterMain)
562
563 def Plugins(**kwargs):
564         return [ PluginDescriptor(name="DiSEqC Tester", description=_("Test DiSEqC settings"), where = PluginDescriptor.WHERE_PLUGINMENU, fnc=DiseqcTesterMain),
565                         PluginDescriptor(where = PluginDescriptor.WHERE_AUTOSTART, fnc = autostart)]