1 from Screens.Satconfig import NimSelection
2 from Screens.Screen import Screen
3 from Screens.TextBox import TextBox
4 from Screens.MessageBox import MessageBox
6 from Plugins.Plugin import PluginDescriptor
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
24 # setResultParameter(parameter)
33 def setResultType(self, type):
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
42 def getTextualResultForIndex(self, index, logfulltransponders = False):
44 text += "%s:\n" % self.getTextualIndexRepresentation(index)
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)
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]
61 text += "The %d unsuccessful tuning attempts failed for the following reasons:\n" % countfailed
63 for reason in reasons.keys():
64 text += "%s: %d transponders failed\n" % (reason, len(reasons[reason]))
66 for reason in reasons.keys():
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]))
73 text += "No transponder tuned"
74 text += " ==> " + self.getTextualIndexRepresentation(self.getIndexForTransponder(transponder[0]))
76 if logfulltransponders:
77 text += str(transponder[1])
79 text += str(transponder[0])
81 if countsuccessful > 0:
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]))
88 text += "No transponder tuned"
89 text += " ==> " + self.getTextualIndexRepresentation(self.getIndexForTransponder(transponder[0]))
93 def getTextualResult(self):
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:
104 for index in self.results.keys():
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"
121 class DiseqcTester(Screen, TuneTest, ResultParser):
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>
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>
132 <widget source="Frontend" render="Label" position="460,35" size="60,22" font="Regular;21">
133 <convert type="FrontendInfo">SNR</convert>
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>
139 <widget source="Frontend" render="Label" position="460,60" size="60,22" font="Regular;21">
140 <convert type="FrontendInfo">AGC</convert>
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>
146 <widget source="Frontend" render="Label" position="460,85" size="60,22" font="Regular;21">
147 <convert type="FrontendInfo">BER</convert>
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" />
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>
158 <widget source="progress_list" render="Listbox" position="0,0" size="510,150" scrollbarMode="showOnDemand">
159 <convert type="TemplatedMultiContent">
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,
164 "fonts": [gFont("Regular", 20)],
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" />
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" />
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" />
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" />
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" />
186 <widget source="CmdText" render="Label" position="300,282" size="180,200" font="Regular;21" />
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)
195 self.test_type = test_type
196 self.loopsfailed = loopsfailed
197 self.loopssuccessful = loopssuccessful
200 self["actions"] = NumberActionMap(["SetupActions"],
203 "cancel": self.keyCancel,
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()
211 self["failed_counter"] = StaticText("0")
212 self["succeeded_counter"] = StaticText("0")
213 self["witherrors_counter"] = StaticText("0")
214 self["untestable_counter"] = StaticText("0")
217 self["progress_list"] = List(self.list)
218 self["progress_list"].onSelectionChanged.append(self.selectionChanged)
220 self["CmdText"] = StaticText(_("Please wait while scanning is in progress..."))
223 self.readTransponderList()
228 self.resultsstatus = {}
230 self.onLayoutFinish.append(self.go)
232 def getProgressListComponent(self, index, status):
233 return (index, self.getTextualIndexRepresentation(index), status)
235 def clearProgressList(self):
237 self["progress_list"].list = self.list
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")
245 self.list.append(self.getProgressListComponent(index, _("working")))
246 self["progress_list"].list = self.list
247 self["progress_list"].setIndex(len(self.list) - 1)
249 def changeProgressListStatus(self, index, status):
253 for entry in self.list:
254 if entry[0] == index:
255 self.newlist.append(self.getProgressListComponent(index, status))
258 self.newlist.append(entry)
260 self.list = self.newlist
261 self["progress_list"].list = self.list
262 self["progress_list"].setIndex(indexpos)
264 def readTransponderList(self):
265 for sat in nimmanager.getSatListForNim(self.feid):
266 for transponder in nimmanager.getTransponders(sat[0]):
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)
271 def getIndexForTransponder(self, transponder):
273 if transponder[0] < 11700:
278 polarisation = transponder[2]
282 index = (band, polarisation, sat)
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
293 # returns a string for the user representing a human readable output for index
294 def getTextualIndexRepresentation(self, index):
295 print "getTextualIndexRepresentation:", index
298 text += nimmanager.getSatDescription(index[2]) + ", "
303 text += "High Band, "
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
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])
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:
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)
341 elif self.test_type == self.TEST_TYPE_RANDOM:
342 self.randomkeys = self.indexlist.keys()
343 random.shuffle(self.randomkeys)
345 self["overall_progress"].setRange(len(self.randomkeys))
346 self["overall_progress"].setValue(self.myindex)
347 return self.randomkeys[0]
348 elif self.test_type == self.TEST_TYPE_COMPLETE:
349 keys = self.indexlist.keys()
353 successorindex[index] = []
354 for otherindex in keys:
355 if otherindex != index:
356 successorindex[index].append(otherindex)
357 random.shuffle(successorindex[index])
362 if currindex is None or len(successorindex[currindex]) == 0:
364 for index in successorindex.keys():
365 if len(successorindex[index]) > 0:
367 self.keylist.append(currindex)
369 if currindex == oldindex:
372 currindex = successorindex[currindex].pop()
373 self.keylist.append(currindex)
374 print "self.keylist:", self.keylist
376 self["overall_progress"].setRange(len(self.keylist))
377 self["overall_progress"].setValue(self.myindex)
378 return self.keylist[0]
381 # after each index is finished, getNextIndex is called to get the next index to scan
382 def getNextIndex(self):
383 # TODO use other function to scan more randomly
384 if self.test_type == self.TEST_TYPE_QUICK:
386 keys = self.indexlist.keys()
387 keys.sort(key = lambda a: a[2]) # sort by orbpos
389 self["overall_progress"].setValue(self.myindex)
390 if self.myindex < len(keys):
391 return keys[self.myindex]
394 elif self.test_type == self.TEST_TYPE_RANDOM:
396 keys = self.randomkeys
398 self["overall_progress"].setValue(self.myindex)
399 if self.myindex < len(keys):
400 return keys[self.myindex]
403 elif self.test_type == self.TEST_TYPE_COMPLETE:
407 self["overall_progress"].setValue(self.myindex)
408 if self.myindex < len(keys):
409 return keys[self.myindex]
413 # after each index is finished and the next index is returned by getNextIndex
414 # the algorithm checks, if we should continue scanning
415 def getContinueScanning(self):
416 if self.test_type == self.TEST_TYPE_QUICK or self.test_type == self.TEST_TYPE_RANDOM:
417 return (self.myindex < len(self.indexlist.keys()))
418 elif self.test_type == self.TEST_TYPE_COMPLETE:
419 return (self.myindex < len(self.keylist))
421 def addResult(self, index, status, failedTune, successfullyTune):
422 self.results[index] = self.results.get(index, {"failed": [], "successful": [], "status": None, "internalstatus": None})
423 self.resultsstatus[status] = self.resultsstatus.get(status, [])
425 oldstatus = self.results[index]["internalstatus"]
426 if oldstatus is None:
427 self.results[index]["status"] = status
428 elif oldstatus == "successful":
429 if status == "failed":
430 self.results[index]["status"] = "with_errors"
431 elif status == "successful":
432 self.results[index]["status"] = oldstatus
433 elif status == "with_errors":
434 self.results[index]["status"] = "with_errors"
435 elif status == "not_tested":
436 self.results[index]["status"] = oldstatus
437 elif oldstatus == "failed":
438 if status == "failed":
439 self.results[index]["status"] = oldstatus
440 elif status == "successful":
441 self.results[index]["status"] = "with_errors"
442 elif status == "with_errors":
443 self.results[index]["status"] = "with_errors"
444 elif status == "not_tested":
445 self.results[index]["status"] = oldstatus
446 elif oldstatus == "with_errors":
447 if status == "failed":
448 self.results[index]["status"] = oldstatus
449 elif status == "successful":
450 self.results[index]["status"] = oldstatus
451 elif status == "with_errors":
452 self.results[index]["status"] = oldstatus
453 elif status == "not_tested":
454 self.results[index]["status"] = oldstatus
455 elif oldstatus == "not_tested":
456 self.results[index]["status"] = status
458 if self.results[index]["status"] != "working":
459 self.results[index]["internalstatus"] = self.results[index]["status"]
460 self.results[index]["failed"] = failedTune + self.results[index]["failed"]
461 self.results[index]["successful"] = successfullyTune + self.results[index]["successful"]
463 self.resultsstatus[status].append(index)
465 def finishedChecking(self):
466 print "finishedChecking"
467 TuneTest.finishedChecking(self)
469 if not self.results.has_key(self.currentlyTestedIndex):
470 self.results[self.currentlyTestedIndex] = {"failed": [], "successful": [], "status": None, "internalstatus": None}
472 if len(self.failedTune) > 0 and len(self.successfullyTune) > 0:
473 self.changeProgressListStatus(self.currentlyTestedIndex, "with errors")
474 self["witherrors_counter"].setText(str(int(self["witherrors_counter"].getText()) + 1))
475 self.addResult(self.currentlyTestedIndex, "with_errors", self.failedTune, self.successfullyTune)
476 elif len(self.failedTune) == 0 and len(self.successfullyTune) == 0:
477 self.changeProgressListStatus(self.currentlyTestedIndex, "not tested")
478 self["untestable_counter"].setText(str(int(self["untestable_counter"].getText()) + 1))
479 self.addResult(self.currentlyTestedIndex, "untestable", self.failedTune, self.successfullyTune)
480 elif len(self.failedTune) > 0:
481 self.changeProgressListStatus(self.currentlyTestedIndex, "failed")
482 #self["failed_counter"].setText(str(int(self["failed_counter"].getText()) + len(self.failedTune)))
483 self["failed_counter"].setText(str(int(self["failed_counter"].getText()) + 1))
484 self.addResult(self.currentlyTestedIndex, "failed", self.failedTune, self.successfullyTune)
486 self.changeProgressListStatus(self.currentlyTestedIndex, "successful")
487 #self["succeeded_counter"].setText(str(int(self["succeeded_counter"].getText()) + len(self.successfullyTune)))
488 self["succeeded_counter"].setText(str(int(self["succeeded_counter"].getText()) + 1))
489 self.addResult(self.currentlyTestedIndex, "successful", self.failedTune, self.successfullyTune)
492 #self["failed_counter"].setText(str(int(self["failed_counter"].getText()) + len(self.failedTune)))
493 #self["succeeded_counter"].setText(str(int(self["succeeded_counter"].getText()) + len(self.successfullyTune)))
494 #if len(self.failedTune) == 0 and len(self.successfullyTune) == 0:
495 #self["untestable_counter"].setText(str(int(self["untestable_counter"].getText()) + 1))
497 self.currentlyTestedIndex = self.getNextIndex()
498 self.addProgressListItem(self.currentlyTestedIndex)
500 if self.fillTransponderList():
501 self.run(checkPIDs = True)
504 self["progress_list"].setIndex(0)
505 print "results:", self.results
506 print "resultsstatus:", self.resultsstatus
508 file = open("/media/hdd/diseqctester.log", "w")
509 self.setResultType(ResultParser.TYPE_ALL)
510 file.write(self.getTextualResult())
512 self.session.open(MessageBox, text=_("The results have been written to %s.") % "/media/hdd/diseqctester.log", type = MessageBox.TYPE_INFO)
516 self["failed_counter"].setText("0")
517 self["succeeded_counter"].setText("0")
518 self["untestable_counter"].setText("0")
519 self.currentlyTestedIndex = self.getFirstIndex()
521 self.clearProgressList()
522 self.addProgressListItem(self.currentlyTestedIndex)
524 if self.fillTransponderList():
531 print "selectedIndex:", self["progress_list"].getCurrent()[0]
533 index = self["progress_list"].getCurrent()[0]
534 #self.setResultType(ResultParser.TYPE_BYORBPOS)
535 #self.setResultParameter(index[2])
536 self.setResultType(ResultParser.TYPE_BYINDEX)
537 self.setResultParameter(index)
538 #self.setResultType(ResultParser.TYPE_ALL)
539 self.session.open(TextBox, self.getTextualResult())
541 def selectionChanged(self):
542 print "selection changed"
543 if len(self.list) > 0 and not self.running:
544 self["CmdText"].setText(_("Press OK to get further details for %s") % str(self["progress_list"].getCurrent()[1]))
546 class DiseqcTesterTestTypeSelection(Screen, ConfigListScreen):
547 skin = """<screen position="80,95" size="560,412" title="DiSEqC Tester Test Settings">
548 <widget name="config" position="10,10" size="540,402" scrollbarMode="showOnDemand" />
551 def __init__(self, session, feid):
552 Screen.__init__(self, session)
556 ConfigListScreen.__init__(self, self.list)
558 self["actions"] = ActionMap(["SetupActions"],
560 "cancel": self.keyCancel
565 def createSetup(self):
566 self.testtype = ConfigSelection(choices={"quick": _("Quick"), "random": _("Random"), "complete": _("Complete")}, default = "quick")
567 self.testtypeEntry = getConfigListEntry(_("Test Type"), self.testtype)
568 self.list.append(self.testtypeEntry)
570 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")
571 self.loopsfailedEntry = getConfigListEntry(_("Stop testing plane after # failed transponders"), self.loopsfailed)
572 self.list.append(self.loopsfailedEntry)
574 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")
575 self.loopssuccessfulEntry = getConfigListEntry(_("Stop testing plane after # successful transponders"), self.loopssuccessful)
576 self.list.append(self.loopssuccessfulEntry)
578 self.log = ConfigYesNo(False)
579 if harddiskmanager.HDDCount() > 0:
580 self.logEntry = getConfigListEntry(_("Log results to harddisk"), self.log)
581 self.list.append(self.logEntry)
583 self["config"].list = self.list
584 self["config"].l.setList(self.list)
587 print self.testtype.getValue()
588 testtype = DiseqcTester.TEST_TYPE_QUICK
589 if self.testtype.getValue() == "quick":
590 testtype = DiseqcTester.TEST_TYPE_QUICK
591 elif self.testtype.getValue() == "random":
592 testtype = DiseqcTester.TEST_TYPE_RANDOM
593 elif self.testtype.getValue() == "complete":
594 testtype = DiseqcTester.TEST_TYPE_COMPLETE
595 self.session.open(DiseqcTester, feid = self.feid, test_type = testtype, loopsfailed = int(self.loopsfailed.value), loopssuccessful = int(self.loopssuccessful.value), log = self.log.value)
600 class DiseqcTesterNimSelection(NimSelection):
602 <screen position="160,123" size="400,330" title="Choose Tuner">
603 <widget source="nimlist" render="Listbox" position="0,0" size="380,300" scrollbarMode="showOnDemand">
604 <convert type="TemplatedMultiContent">
606 MultiContentEntryText(pos = (10, 5), size = (360, 30), flags = RT_HALIGN_LEFT, text = 1), # index 1 is the nim name,
607 MultiContentEntryText(pos = (50, 30), size = (320, 30), font = 1, flags = RT_HALIGN_LEFT, text = 2), # index 2 is a description of the nim settings,
609 "fonts": [gFont("Regular", 20), gFont("Regular", 15)],
616 def __init__(self, session, args = None):
617 NimSelection.__init__(self, session)
619 def setResultClass(self):
620 #self.resultclass = DiseqcTester
621 self.resultclass = DiseqcTesterTestTypeSelection
623 def showNim(self, nim):
624 nimConfig = nimmanager.getNimConfig(nim.slot)
625 if nim.isCompatible("DVB-S"):
626 if nimConfig.configMode.value in ["loopthrough", "equal", "satposdepends", "nothing"]:
628 if nimConfig.configMode.value == "simple":
629 if nimConfig.diseqcMode.value == "positioner":
634 def DiseqcTesterMain(session, **kwargs):
635 session.open(DiseqcTesterNimSelection)
637 def autostart(reason, **kwargs):
638 resourcemanager.addResource("DiseqcTester", DiseqcTesterMain)
640 def Plugins(**kwargs):
641 return [ PluginDescriptor(name="DiSEqC Tester", description=_("Test DiSEqC settings"), where = PluginDescriptor.WHERE_PLUGINMENU, fnc=DiseqcTesterMain),
642 PluginDescriptor(where = PluginDescriptor.WHERE_AUTOSTART, fnc = autostart)]