e24a106675231d50d4e282a3ba4f0b512bfde905
[vuplus_dvbapp] / lib / python / Plugins / SystemPlugins / Blindscan / plugin.py
1 from Plugins.Plugin import PluginDescriptor
2
3 from Screens.Screen import Screen
4 from Screens.ServiceScan import ServiceScan
5 from Screens.MessageBox import MessageBox
6 from Screens.DefaultWizard import DefaultWizard
7
8 from Components.Label import Label
9 from Components.TuneTest import Tuner
10 from Components.ConfigList import ConfigListScreen
11 from Components.Sources.StaticText import StaticText
12 from Components.ActionMap import NumberActionMap, ActionMap
13 from Components.NimManager import nimmanager, getConfigSatlist
14 from Components.config import config, ConfigSubsection, ConfigSelection, ConfigYesNo, ConfigInteger, getConfigListEntry, ConfigSlider, ConfigEnableDisable
15
16 from Tools.HardwareInfo import HardwareInfo
17 from Tools.Directories import resolveFilename, SCOPE_DEFAULTPARTITIONMOUNTDIR, SCOPE_DEFAULTDIR, SCOPE_DEFAULTPARTITION
18
19 from enigma import eTimer, eDVBFrontendParametersSatellite, eComponentScan, eDVBSatelliteEquipmentControl, eDVBFrontendParametersTerrestrial, eDVBFrontendParametersCable, eConsoleAppContainer, eDVBResourceManager
20
21 class Blindscan(ConfigListScreen, Screen):
22         skin="""
23                 <screen name="Blindscan" position="center,center" size="560,290" title="Blindscan">
24                         <ePixmap pixmap="Vu_HD/buttons/red.png" position="5,0" size="140,40" alphatest="on" />
25                         <ePixmap pixmap="Vu_HD/buttons/green.png" position="145,0" size="140,40" alphatest="on" />
26                         <ePixmap pixmap="Vu_HD/buttons/button_off.png" position="285,0" size="140,40" alphatest="on" />
27                         <ePixmap pixmap="Vu_HD/buttons/blue.png" position="425,0" size="140,40" alphatest="on" />
28                         <widget source="key_red" render="Label" position="20,0" zPosition="1" size="115,30" font="Regular;20" halign="center" valign="center" transparent="1" />
29                         <widget source="key_green" render="Label" position="160,0" zPosition="1" size="115,30" font="Regular;20" halign="center" valign="center" transparent="1" />
30                         <widget source="key_blue" render="Label" position="440,0" zPosition="1" size="115,30" font="Regular;20" halign="center" valign="center" transparent="1" />
31                         <widget name="config" position="5,50" size="550,200" scrollbarMode="showOnDemand" />
32                         <widget name="introduction" position="0,265" size="560,20" font="Regular;20" halign="center" />
33                 </screen>
34                 """
35         def __init__(self, session): 
36                 Screen.__init__(self, session)
37
38                 self.current_play_service = self.session.nav.getCurrentlyPlayingServiceReference()
39
40                 # update sat list
41                 self.satList = []
42                 for slot in nimmanager.nim_slots:
43                         if slot.isCompatible("DVB-S"):
44                                 self.satList.append(nimmanager.getSatListForNim(slot.slot))
45
46                 # make config
47                 self.createConfig()
48
49                 self.list = []
50                 self.status = ""
51
52                 ConfigListScreen.__init__(self, self.list)
53                 if self.scan_nims.value != None and self.scan_nims.value != "" :
54                         self["actions"] = ActionMap(["OkCancelActions", "ShortcutActions", "WizardActions", "ColorActions", "SetupActions", ],
55                         {
56                                 "red": self.keyCancel,
57                                 "green": self.keyGo,
58                                 "blue":self.keyGoAll,
59                                 "ok": self.keyGo,
60                                 "cancel": self.keyCancel,
61                         }, -2)
62                         self["key_red"] = StaticText(_("Exit"))
63                         self["key_green"] = StaticText("Start")
64                         self["key_blue"] = StaticText("Scan All")
65                         self["introduction"] = Label(_("Press Green/OK to start the scan"))
66                         self.createSetup()
67                 else :
68                         self["actions"] = ActionMap(["OkCancelActions", "ShortcutActions", "WizardActions", "ColorActions", "SetupActions", ],
69                         {
70                                 "red": self.keyCancel,
71                                 "green": self.keyNone,
72                                 "blue":self.keyNone,
73                                 "ok": self.keyNone,
74                                 "cancel": self.keyCancel,
75                         }, -2)
76                         self["key_red"] = StaticText(_("Exit"))
77                         self["key_green"] = StaticText(" ")
78                         self["key_blue"] = StaticText(" ")
79                         self["introduction"] = Label(_("Please setup your tuner configuration."))
80
81         def keyNone(self):
82                 None
83         def callbackNone(self, *retval):
84                 None
85
86         def openFrontend(self):
87                 res_mgr = eDVBResourceManager.getInstance()
88                 if res_mgr:
89                         self.raw_channel = res_mgr.allocateRawChannel(self.feid)
90                         if self.raw_channel:
91                                 self.frontend = self.raw_channel.getFrontend()
92                                 if self.frontend:
93                                         return True
94                                 else:
95                                         print "getFrontend failed"
96                         else:
97                                 print "getRawChannel failed"
98                 else:
99                         print "getResourceManager instance failed"
100                 return False
101
102         def createConfig(self):
103                 self.feinfo = None
104                 frontendData = None
105                 defaultSat = {
106                         "orbpos": 192,
107                         "system": eDVBFrontendParametersSatellite.System_DVB_S,
108                         "frequency": 11836,
109                         "inversion": eDVBFrontendParametersSatellite.Inversion_Unknown,
110                         "symbolrate": 27500,
111                         "polarization": eDVBFrontendParametersSatellite.Polarisation_Horizontal,
112                         "fec": eDVBFrontendParametersSatellite.FEC_Auto,
113                         "fec_s2": eDVBFrontendParametersSatellite.FEC_9_10,
114                         "modulation": eDVBFrontendParametersSatellite.Modulation_QPSK 
115                 }
116
117                 self.service = self.session.nav.getCurrentService()
118                 if self.service is not None:
119                         self.feinfo = self.service.frontendInfo()
120                         frontendData = self.feinfo and self.feinfo.getAll(True)
121                 if frontendData is not None:
122                         ttype = frontendData.get("tuner_type", "UNKNOWN")
123                         if ttype == "DVB-S":
124                                 defaultSat["system"] = frontendData.get("system", eDVBFrontendParametersSatellite.System_DVB_S)
125                                 defaultSat["frequency"] = frontendData.get("frequency", 0) / 1000
126                                 defaultSat["inversion"] = frontendData.get("inversion", eDVBFrontendParametersSatellite.Inversion_Unknown)
127                                 defaultSat["symbolrate"] = frontendData.get("symbol_rate", 0) / 1000
128                                 defaultSat["polarization"] = frontendData.get("polarization", eDVBFrontendParametersSatellite.Polarisation_Horizontal)
129                                 if defaultSat["system"] == eDVBFrontendParametersSatellite.System_DVB_S2:
130                                         defaultSat["fec_s2"] = frontendData.get("fec_inner", eDVBFrontendParametersSatellite.FEC_Auto)
131                                         defaultSat["rolloff"] = frontendData.get("rolloff", eDVBFrontendParametersSatellite.RollOff_alpha_0_35)
132                                         defaultSat["pilot"] = frontendData.get("pilot", eDVBFrontendParametersSatellite.Pilot_Unknown)
133                                 else:
134                                         defaultSat["fec"] = frontendData.get("fec_inner", eDVBFrontendParametersSatellite.FEC_Auto)
135                                 defaultSat["modulation"] = frontendData.get("modulation", eDVBFrontendParametersSatellite.Modulation_QPSK)
136                                 defaultSat["orbpos"] = frontendData.get("orbital_position", 0)
137                 del self.feinfo
138                 del self.service
139                 del frontendData
140                 
141                 self.scan_sat = ConfigSubsection()
142                 self.scan_networkScan = ConfigYesNo(default = False)
143                 
144                 # blindscan add
145                 self.blindscan_hi = ConfigSelection(default = "hi_low", choices = [("low", _("low")), ("high", _("high")), ("hi_low", _("hi_low"))])
146
147                 #ConfigYesNo(default = True)
148                 self.blindscan_start_frequency = ConfigInteger(default = 950*1000000)
149                 self.blindscan_stop_frequency = ConfigInteger(default = 2150*1000000)
150                 self.blindscan_start_symbol = ConfigInteger(default = 2*1000000)
151                 self.blindscan_stop_symbol = ConfigInteger(default = 45*1000000)
152
153                 # collect all nims which are *not* set to "nothing"
154                 nim_list = []
155                 for n in nimmanager.nim_slots:
156                         if n.config_mode == "nothing":
157                                 continue
158                         if n.config_mode == "advanced" and len(nimmanager.getSatListForNim(n.slot)) < 1:
159                                 continue
160                         if n.config_mode in ("loopthrough", "satposdepends"):
161                                 root_id = nimmanager.sec.getRoot(n.slot_id, int(n.config.connectedTo.value))
162                                 if n.type == nimmanager.nim_slots[root_id].type: # check if connected from a DVB-S to DVB-S2 Nim or vice versa
163                                         continue
164                         nim_list.append((str(n.slot), n.friendly_full_description))
165
166                 self.scan_nims = ConfigSelection(choices = nim_list)
167
168                 # sat
169                 self.scan_sat.frequency = ConfigInteger(default = defaultSat["frequency"], limits = (1, 99999))
170                 #self.scan_sat.polarization = ConfigSelection(default = defaultSat["polarization"], choices = [
171                 self.scan_sat.polarization = ConfigSelection(default = eDVBFrontendParametersSatellite.Polarisation_CircularRight + 1, choices = [
172                         (eDVBFrontendParametersSatellite.Polarisation_CircularRight + 1, _("horizontal_vertical")),
173                         (eDVBFrontendParametersSatellite.Polarisation_Horizontal, _("horizontal")),
174                         (eDVBFrontendParametersSatellite.Polarisation_Vertical, _("vertical")),
175                         (eDVBFrontendParametersSatellite.Polarisation_CircularLeft, _("circular left")),
176                         (eDVBFrontendParametersSatellite.Polarisation_CircularRight, _("circular right"))])
177                 self.scan_scansat = {}
178                 for sat in nimmanager.satList:
179                         self.scan_scansat[sat[0]] = ConfigYesNo(default = False)
180                 
181                 self.scan_satselection = []
182                 for slot in nimmanager.nim_slots:
183                         if slot.isCompatible("DVB-S"):
184                                 self.scan_satselection.append(getConfigSatlist(defaultSat["orbpos"], self.satList[slot.slot]))
185                 return True
186
187         def createSetup(self):
188                 self.list = []
189                 self.multiscanlist = []
190                 index_to_scan = int(self.scan_nims.value)
191                 print "ID: ", index_to_scan
192
193                 self.tunerEntry = getConfigListEntry(_("Tuner"), self.scan_nims)
194                 self.list.append(self.tunerEntry)
195                 
196                 if self.scan_nims == [ ]:
197                         return
198                 
199                 self.systemEntry = None
200                 self.modulationEntry = None
201                 nim = nimmanager.nim_slots[index_to_scan]
202
203                 self.scan_networkScan.value = False
204                 if nim.isCompatible("DVB-S") :
205                         self.list.append(getConfigListEntry(_('Satellite'), self.scan_satselection[index_to_scan]))
206                         self.list.append(getConfigListEntry(_('Scan start frequency'), self.blindscan_start_frequency))
207                         self.list.append(getConfigListEntry(_('Scan stop frequency'), self.blindscan_stop_frequency))
208                         self.list.append(getConfigListEntry(_("Polarity"), self.scan_sat.polarization))
209                         self.list.append(getConfigListEntry(_("Scan band"), self.blindscan_hi))
210                         self.list.append(getConfigListEntry(_('Scan start symbolrate'), self.blindscan_start_symbol))
211                         self.list.append(getConfigListEntry(_('Scan stop symbolrate'), self.blindscan_stop_symbol))
212                         self["config"].list = self.list
213                         self["config"].l.setList(self.list)
214                         
215         def newConfig(self):
216                 cur = self["config"].getCurrent()
217                 print "cur is", cur
218                 if cur == self.tunerEntry or \
219                         cur == self.systemEntry or \
220                         (self.modulationEntry and self.systemEntry[1].value == eDVBFrontendParametersSatellite.System_DVB_S2 and cur == self.modulationEntry):
221                         self.createSetup()
222
223         def checkSettings(self):
224                 if self.blindscan_start_frequency.value < 950*1000000 or self.blindscan_start_frequency.value > 2150*1000000 :
225                         self.session.open(MessageBox, _("Please check again.\nStart frequency must be between 950 and 2150."), MessageBox.TYPE_ERROR)
226                         return False
227                 if self.blindscan_stop_frequency.value < 950*1000000 or self.blindscan_stop_frequency.value > 2150*1000000 :
228                         self.session.open(MessageBox, _("Please check again.\nStop frequency must be between 950 and 2150."), MessageBox.TYPE_ERROR)
229                         return False
230                 if self.blindscan_start_frequency.value > self.blindscan_stop_frequency.value :
231                         self.session.open(MessageBox, _("Please check again.\nFrequency : start value is larger than stop value."), MessageBox.TYPE_ERROR)
232                         return False
233                 if self.blindscan_start_symbol.value < 2*1000000 or self.blindscan_start_symbol.value > 45*1000000 :
234                         self.session.open(MessageBox, _("Please check again.\nStart symbolrate must be between 2MHz and 45MHz."), MessageBox.TYPE_ERROR)
235                         return False
236                 if self.blindscan_stop_symbol.value < 2*1000000 or self.blindscan_stop_symbol.value > 45*1000000 :
237                         self.session.open(MessageBox, _("Please check again.\nStop symbolrate must be between 2MHz and 45MHz."), MessageBox.TYPE_ERROR)
238                         return False
239                 if self.blindscan_start_symbol.value > self.blindscan_stop_symbol.value :
240                         self.session.open(MessageBox, _("Please check again.\nSymbolrate : start value is larger than stop value."), MessageBox.TYPE_ERROR)
241                         return False
242                 return True
243
244         def keyLeft(self):
245                 ConfigListScreen.keyLeft(self)
246                 self.newConfig()
247
248         def keyRight(self):
249                 ConfigListScreen.keyRight(self)
250                 self.newConfig()
251                         
252         def keyCancel(self):
253                 self.session.nav.playService(self.current_play_service)
254                 for x in self["config"].list:
255                         x[1].cancel()
256                 self.close()
257
258         def keyGo(self):
259                 if self.checkSettings() == False:
260                         return
261
262                 tab_pol = {
263                         eDVBFrontendParametersSatellite.Polarisation_Horizontal : "horizontal", 
264                         eDVBFrontendParametersSatellite.Polarisation_Vertical : "vertical",
265                         eDVBFrontendParametersSatellite.Polarisation_CircularLeft : "circular left",
266                         eDVBFrontendParametersSatellite.Polarisation_CircularRight : "circular right",
267                         eDVBFrontendParametersSatellite.Polarisation_CircularRight + 1 : "horizontal_vertical"
268                 }
269
270                 self.tmp_tplist=[]
271                 tmp_pol = []
272                 tmp_band = []
273                 tmp_list=[self.satList[0][self.scan_satselection[0].index]]
274                 
275                 if self.blindscan_hi.value == "hi_low" :
276                         tmp_band=["low","high"]
277                 else:
278                         tmp_band=[self.blindscan_hi.value]
279                         
280                 if self.scan_sat.polarization.value ==  eDVBFrontendParametersSatellite.Polarisation_CircularRight + 1 : 
281                         tmp_pol=["horizontal","vertical"]
282                 else:
283                         tmp_pol=[tab_pol[self.scan_sat.polarization.value]]
284
285                 self.doRun(tmp_list, tmp_pol, tmp_band)
286                 
287         def keyGoAll(self):
288                 if self.checkSettings() == False:
289                         return
290
291                 self.tmp_tplist=[]
292                 tmp_list=[]
293                 tmp_band=["low","high"]
294                 tmp_pol=["horizontal","vertical"]
295                 for slot in nimmanager.nim_slots:
296                         if slot.isCompatible("DVB-S"):
297                                 for s in self.satList[slot.slot]:
298                                         tmp_list.append(s)
299
300                 self.doRun(tmp_list, tmp_pol, tmp_band)
301                 
302         def doRun(self, tmp_list, tmp_pol, tmp_band):
303                 self.total_list=[]
304                 for x in tmp_list:
305                         for y in tmp_pol:
306                                 for z in tmp_band:
307                                         self.total_list.append([x,y,z])
308                                         print "add scan item : ", x, ", ", y, ", ", z
309
310                 self.max_count = len(self.total_list)
311                 self.is_runable = True
312                 self.running_count = 0
313                 self.clockTimer = eTimer()
314                 self.clockTimer.callback.append(self.doClock)
315                 self.clockTimer.start(1000)
316
317         def doClock(self):
318                 is_scan = False
319                 if self.is_runable :
320                         if self.running_count >= self.max_count:
321                                 self.clockTimer.stop()
322                                 del self.clockTimer
323                                 self.clockTimer = None
324                                 print "Done"
325                                 return
326                         orb = self.total_list[self.running_count][0]
327                         pol = self.total_list[self.running_count][1]
328                         band = self.total_list[self.running_count][2]
329                         self.running_count = self.running_count + 1
330                         print "running status-[%d] : [%d][%s][%s]" %(self.running_count, orb[0], pol, band)
331                         if self.running_count == self.max_count:
332                                 is_scan = True
333                         self.prepareScanData(orb, pol, band, is_scan)
334
335         def prepareScanData(self, orb, pol, band, is_scan):
336                 self.is_runable = False
337                 self.orb_position = orb[0]
338                 self.feid = int(self.scan_nims.value)
339                 tab_hilow = {"high" : 1, "low" : 0}
340                 tab_pol = {
341                         "horizontal" : eDVBFrontendParametersSatellite.Polarisation_Horizontal, 
342                         "vertical" : eDVBFrontendParametersSatellite.Polarisation_Vertical,
343                         "circular left" : eDVBFrontendParametersSatellite.Polarisation_CircularLeft,
344                         "circular right" : eDVBFrontendParametersSatellite.Polarisation_CircularRight
345                 }
346
347                 returnvalue = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
348
349                 if not self.openFrontend():
350                         self.oldref = self.session.nav.getCurrentlyPlayingServiceReference()
351                         self.session.nav.stopService()
352                         if not self.openFrontend():
353                                 if self.session.pipshown:
354                                         self.session.pipshown = False
355                                         del self.session.pip
356                                         if not self.openFrontend():
357                                                 self.frontend = None
358                 self.tuner = Tuner(self.frontend)
359
360                 if tab_hilow[band]:
361                         self.scan_sat.frequency.value = 12515
362                 else:
363                         self.scan_sat.frequency.value = 11015
364                 returnvalue = (self.scan_sat.frequency.value,
365                                          0,
366                                          tab_pol[pol],
367                                          0,
368                                          0,
369                                          orb[0],
370                                          eDVBFrontendParametersSatellite.System_DVB_S,
371                                          0,
372                                          0,
373                                          0)
374                 self.tuner.tune(returnvalue)
375
376                 cmd = "vuplus_blindscan %d %d %d %d %d %d %d" % (self.blindscan_start_frequency.value/1000000, self.blindscan_stop_frequency.value/1000000, self.blindscan_start_symbol.value/1000000, self.blindscan_stop_symbol.value/1000000, tab_pol[pol], tab_hilow[band], self.feid)
377                 print "prepared command : [%s]" % (cmd)
378                 self.blindscan_container = eConsoleAppContainer()
379                 self.blindscan_container.appClosed.append(self.blindscanContainerClose)
380                 self.blindscan_container.dataAvail.append(self.blindscanContainerAvail)
381                 self.blindscan_container.execute(cmd)
382
383                 tmpstr = "Look for available transponders.\nThis works will take several minutes.\n\n   - Current Status : %d/%d\n   - Orbital Positions : %s\n   - Polarization : %s\n   - Bandwidth : %s" %(self.running_count, self.max_count, orb[1], pol, band)
384                 if is_scan :
385                         self.blindscan_session = self.session.openWithCallback(self.blindscanSessionClose, MessageBox, _(tmpstr), MessageBox.TYPE_INFO)
386                 else:
387                         self.blindscan_session = self.session.openWithCallback(self.blindscanSessionNone, MessageBox, _(tmpstr), MessageBox.TYPE_INFO)
388
389         def blindscanContainerClose(self, retval):
390                 self.blindscan_session.close(True)
391
392         def blindscanContainerAvail(self, str):
393                 lines = str.split('\n')
394                 for line in lines:
395                         data = line.split()
396                         if len(data):
397                                 print data
398                                 if data[0] == 'OK':
399                                         parm = eDVBFrontendParametersSatellite()
400                                         sys = {         "DVB-S" : eDVBFrontendParametersSatellite.System_DVB_S,
401                                                         "DVB-S2" : eDVBFrontendParametersSatellite.System_DVB_S2        }
402                                         qam = {         "QPSK" : parm.Modulation_QPSK,
403                                                         "8PSK" : parm.Modulation_8PSK }
404                                         inv = {         "INVERSION_OFF" : parm.Inversion_Off,
405                                                         "INVERSION_ON" : parm.Inversion_On,
406                                                         "INVERSION_AUTO" : parm.Inversion_Unknown }
407                                         fec = {         "FEC_AUTO" : parm.FEC_Auto,
408                                                         "FEC_1_2" : parm.FEC_1_2,
409                                                         "FEC_2_3" : parm.FEC_2_3,
410                                                         "FEC_3_4" : parm.FEC_3_4,
411                                                         "FEC_5_6": parm.FEC_5_6,
412                                                         "FEC_7_8" : parm.FEC_7_8,
413                                                         "FEC_8_9" : parm.FEC_8_9,
414                                                         "FEC_3_5" : parm.FEC_3_5,
415                                                         "FEC_9_10" : parm.FEC_9_10,
416                                                         "FEC_NONE" : parm.FEC_None }
417                                         roll = {        "ROLLOFF_20" : parm.RollOff_alpha_0_20,
418                                                         "ROLLOFF_25" : parm.RollOff_alpha_0_25,
419                                                         "ROLLOFF_35" : parm.RollOff_alpha_0_35 }
420                                         pilot = {       "PILOT_ON" : parm.Pilot_On,
421                                                         "PILOT_OFF" : parm.Pilot_Off }
422                                         pol = { "HORIZONTAL" : parm.Polarisation_Horizontal,
423                                                         "VERTICAL" : parm.Polarisation_Vertical }
424                                         parm.orbital_position = self.orb_position
425                                         parm.polarisation = pol[data[1]]
426                                         parm.frequency = int(data[2])
427                                         parm.symbol_rate = int(data[3])
428                                         parm.system = sys[data[4]]
429                                         parm.inversion = inv[data[5]]
430                                         parm.pilot = pilot[data[6]]
431                                         parm.fec = fec[data[7]]
432                                         parm.modulation = qam[data[8]]
433                                         parm.rolloff = roll[data[9]]
434                                         self.tmp_tplist.append(parm)
435
436         def blindscanSessionNone(self, *val):
437                 import time
438                 self.blindscan_container.sendCtrlC()
439                 self.blindscan_container = None
440                 time.sleep(2)
441
442                 if self.frontend:
443                         self.frontend = None
444                         del self.raw_channel
445
446                 if val[0] == False:
447                         self.tmp_tplist = []
448                         self.running_count = self.max_count
449                         
450                 self.is_runable = True
451                 
452         def blindscanSessionClose(self, *val):
453                 self.blindscanSessionNone(val[0])
454
455                 if self.tmp_tplist != None and self.tmp_tplist != []:
456                         for p in self.tmp_tplist:
457                                 print "data : [%d][%d][%d][%d][%d][%d][%d][%d][%d][%d]" % (p.orbital_position, p.polarisation, p.frequency, p.symbol_rate, p.system, p.inversion, p.pilot, p.fec, p.modulation, p.modulation)
458
459                         self.startScan(self.tmp_tplist, self.feid)
460                 else:
461                         msg = "No found transponders!!\nPlease check the satellite connection, or scan other search condition." 
462                         if val[0] == False:
463                                 msg = "Blindscan was canceled by the user."
464                         self.session.openWithCallback(self.callbackNone, MessageBox, _(msg), MessageBox.TYPE_INFO, timeout=10)
465                         self.tmp_tplist = []
466
467         def startScan(self, tlist, feid, networkid = 0):
468                 self.scan_session = None
469                 self.session.open(ServiceScan, [{"transponders": tlist, "feid": feid, "flags": 0, "networkid": networkid}])
470
471 def main(session, **kwargs):
472         session.open(Blindscan)
473                                                            
474 def Plugins(**kwargs):            
475         return PluginDescriptor(name=_("Blindscan"), description="scan type(DVB-S)", where = PluginDescriptor.WHERE_PLUGINMENU, fnc=main)
476