enigma2: 4.3.1r10
[enigma2.git] / usr / lib / enigma2 / python / Components / NimManager.py
1 from Tools.HardwareInfo import HardwareInfo
2 from Tools.BoundFunction import boundFunction
3
4 from config import config, ConfigSubsection, ConfigSelection, ConfigFloat, \
5         ConfigSatlist, ConfigYesNo, ConfigInteger, ConfigSubList, ConfigNothing, \
6         ConfigSubDict, ConfigOnOff, ConfigDateTime, ConfigText, NoSave, ConfigSet
7
8 from enigma import eDVBSatelliteEquipmentControl as secClass, \
9         eDVBSatelliteDiseqcParameters as diseqcParam, \
10         eDVBSatelliteSwitchParameters as switchParam, \
11         eDVBSatelliteRotorParameters as rotorParam, \
12         eDVBResourceManager, eDVBDB, eEnv, iDVBFrontend
13
14 from time import localtime, mktime
15 from datetime import datetime
16 from os.path import exists
17
18 import xml.etree.cElementTree
19
20 from Tools.Log import Log
21
22 from ast import literal_eval
23
24 def getConfigSatlist(orbpos, satlist):
25         default_orbpos = None
26         for x in satlist:
27                 if x[0] == orbpos:
28                         default_orbpos = orbpos
29                         break
30         return ConfigSatlist(satlist, default_orbpos)
31
32 def tryOpen(filename):
33         try:
34                 procFile = open(filename)
35         except IOError:
36                 return None
37         return procFile
38
39 class SecConfigure:
40         def getConfiguredSats(self):
41                 return self.configuredSatellites
42
43         def addSatellite(self, sec, orbpos):
44                 sec.addSatellite(orbpos)
45                 self.configuredSatellites.add(orbpos)
46
47         def addLNBSimple(self, sec, slotid, input, diseqcmode, toneburstmode = diseqcParam.NO, diseqcpos = diseqcParam.SENDNO, orbpos = 0, longitude = 0, latitude = 0, loDirection = 0, laDirection = 0, turningSpeed = rotorParam.FAST, useInputPower=True, inputPowerDelta=50, fastDiSEqC = False, setVoltageTone = True, diseqc13V = False, degreePerSecond = 0.5):
48                 if orbpos is None or orbpos == 3601:
49                         return
50                 #simple defaults
51                 sec.addLNB()
52                 sec.setLNBTunerInput(input)
53
54                 tunermask = 1 << slotid
55                 if input == -1:
56                         if self.equal.has_key(slotid):
57                                 for slot in self.equal[slotid]:
58                                         tunermask |= (1 << slot)
59                         if self.linked.has_key(slotid):
60                                 for slot in self.linked[slotid]:
61                                         tunermask |= (1 << slot)
62
63                 sec.setLNBSatCR(-1)
64                 sec.setLNBNum(1)
65                 sec.setLNBLOFL(9750000)
66                 sec.setLNBLOFH(10600000)
67                 sec.setLNBThreshold(11700000)
68                 sec.setLNBIncreasedVoltage(False)
69                 sec.setRepeats(0)
70                 sec.setFastDiSEqC(fastDiSEqC)
71                 sec.setSeqRepeat(0)
72                 sec.setCommandOrder(0)
73
74                 #user values
75                 sec.setDiSEqCMode(diseqcmode)
76                 sec.setToneburst(toneburstmode)
77                 sec.setCommittedCommand(diseqcpos)
78                 sec.setUncommittedCommand(0) # SENDNO
79                 #print "set orbpos to:" + str(orbpos)
80
81                 if 0 <= diseqcmode < 3:
82                         Log.i("add sat " + str(orbpos))
83                         self.addSatellite(sec, orbpos)
84                         if setVoltageTone:
85                                 if diseqc13V:
86                                         sec.setVoltageMode(switchParam.HV_13)
87                                 else:
88                                         sec.setVoltageMode(switchParam.HV)
89                                 sec.setToneMode(switchParam.HILO)
90                         else:
91                                 sec.setVoltageMode(switchParam._14V)
92                                 sec.setToneMode(switchParam.OFF)
93                 elif (diseqcmode == 3): # diseqc 1.2
94                         if self.satposdepends.has_key(slotid):
95                                 for slot in self.satposdepends[slotid]:
96                                         tunermask |= (1 << slot)
97                         sec.setLatitude(latitude)
98                         sec.setLaDirection(laDirection)
99                         sec.setLongitude(longitude)
100                         sec.setLoDirection(loDirection)
101                         sec.setUseInputpower(useInputPower)
102                         sec.setInputpowerDelta(inputPowerDelta)
103                         sec.setRotorTurningSpeed(turningSpeed)
104                         sec.setDegreePerSecond(int(degreePerSecond*10))
105
106                         Log.i("add rotor satellites")
107                         for x in self.NimManager.satList:
108                                 self.addSatellite(sec, int(x[0]))
109                                 if diseqc13V:
110                                         sec.setVoltageMode(switchParam.HV_13)
111                                 else:
112                                         sec.setVoltageMode(switchParam.HV)
113                                 sec.setToneMode(switchParam.HILO)
114                                 sec.setRotorPosNum(0) # USALS
115
116                 sec.setLNBSlotMask(tunermask)
117
118         def setSatposDepends(self, sec, nim1, nim2):
119                 Log.i("tuner " + str(nim1) + " depends on satpos of " + str(nim2))
120                 sec.setTunerDepends(nim1, nim2)
121
122         def linkInternally(self, slotid):
123                 nim = self.NimManager.getNim(slotid)
124                 nim.setInternalLink()
125
126         def linkNIMs(self, sec, nim1, nim2):
127                 if abs(nim2  - nim1) == 1:
128                         Log.i("internal link tuner " + str(nim1) + " to tuner " + str(nim2))
129                         self.linkInternally(nim1)
130                 else:
131                         Log.i("external link tuner " + str(nim1) + " to tuner " + str(nim2))
132                 sec.setTunerLinked(nim1, nim2)
133
134         def getRoot(self, slotid, connto):
135                 visited = []
136                 while (self.NimManager.getNimConfig(connto).sat.configMode.value in ("satposdepends", "equal", "loopthrough")):
137                         connto = int(self.NimManager.getNimConfig(connto).connectedTo.value)
138                         if connto in visited: # prevent endless loop
139                                 return slotid
140                         visited.append(connto)
141                 return connto
142
143         def update(self):
144                 sec = secClass.getInstance()
145                 self.configuredSatellites = set()
146                 for slotid in self.NimManager.getNimListOfType("DVB-S"):
147                         if self.NimManager.nimInternallyConnectableTo(slotid) is not None:
148                                 self.NimManager.nimRemoveInternalLink(slotid)
149                 sec.clear() ## this do unlinking NIMs too !!
150
151                 Log.i("sec config cleared")
152
153                 self.linked = { }
154                 self.satposdepends = { }
155                 self.equal = { }
156
157                 nim_slots = self.NimManager.nim_slots
158
159                 used_nim_slots = [ ]
160
161                 multi_tuner_slot_base = -1
162                 multi_tuner_slot_channel = 0
163
164                 for slot in nim_slots:
165                         enabled = 0
166
167                         # handling for tuners with multiple channels
168                         if slot.inputs:
169                                 if multi_tuner_slot_base == -1 or slot.channel <= multi_tuner_slot_channel:
170                                         multi_tuner_slot_base = slot.slot
171                                         multi_tuner_slot_channel = 0
172                                 else:
173                                         multi_tuner_slot_channel += 1
174                                 def isEnabled(type):
175                                         for inp in xrange(len(slot.inputs)):
176                                                 if nim_slots[multi_tuner_slot_base+inp].isEnabled(type):
177                                                         return True
178                                         return False
179                                 enabledFunc = isEnabled
180                         else:
181                                 multi_tuner_slot_base = -1
182                                 multi_tuner_slot_channel = 0
183                                 enabledFunc = slot.isEnabled
184
185                         if enabledFunc("DVB-S2"):
186                                 enabled |= iDVBFrontend.feSatellite2
187                         if enabledFunc("DVB-S"):
188                                 enabled |= iDVBFrontend.feSatellite
189                         if enabledFunc("DVB-T2"):
190                                 enabled |= iDVBFrontend.feTerrestrial2
191                         if enabledFunc("DVB-T"):
192                                 enabled |= iDVBFrontend.feTerrestrial
193                         if enabledFunc("DVB-C"):
194                                 enabled |= iDVBFrontend.feCable
195
196                         used_nim_slots.append((slot.slot, slot.description, enabled, slot.frontend_id is None and -1 or slot.frontend_id, slot.input_name or "", multi_tuner_slot_base, multi_tuner_slot_base+slot.channels-1))
197
198                 # this have to be called before tuners can be linked to other tuners!!!!!!!!
199                 eDVBResourceManager.getInstance().setFrontendSlotInformations(used_nim_slots)
200
201                 # please do not mix this loop with the following one...
202                 # this code must be run before the next loop
203                 for slot in nim_slots:
204                         x = slot.slot
205                         nim = slot.config
206
207                         # FIXMEE
208                         # no support for satpos depends, equal to and loopthough setting for nims with
209                         # with multiple inputs and multiple channels
210                         if slot.isEnabled("DVB-S") and not slot.inputs:
211                                 # save what nim we link to/are equal to/satposdepends to.
212                                 # this is stored in the *value* (not index!) of the config list
213                                 if nim.sat.configMode.value == "equal":
214                                         connto = self.getRoot(x, int(nim.connectedTo.value))
215                                         if not self.equal.has_key(connto):
216                                                 self.equal[connto] = []
217                                         self.equal[connto].append(x)
218                                 elif nim.sat.configMode.value == "loopthrough":
219                                         self.linkNIMs(sec, x, int(nim.connectedTo.value))
220                                         connto = self.getRoot(x, int(nim.connectedTo.value))
221                                         if not self.linked.has_key(connto):
222                                                 self.linked[connto] = []
223                                         self.linked[connto].append(x)
224                                 elif nim.sat.configMode.value == "satposdepends":
225                                         self.setSatposDepends(sec, x, int(nim.connectedTo.value))
226                                         connto = self.getRoot(x, int(nim.connectedTo.value))
227                                         if not self.satposdepends.has_key(connto):
228                                                 self.satposdepends[connto] = []
229                                         self.satposdepends[connto].append(x)
230
231                 multi_tuner_slot_base = -1
232                 multi_tuner_slot_channel = 0
233
234                 for sl in nim_slots:
235
236                         # handling for tuners with multiple channels
237                         if sl.inputs:
238                                 inputs = len(sl.inputs)
239                                 if multi_tuner_slot_base == -1 or sl.channel <= multi_tuner_slot_channel:
240                                         multi_tuner_slot_base = sl.slot
241                                         multi_tuner_slot_channel = 0
242                                 else:
243                                         multi_tuner_slot_channel += 1
244                         else:
245                                 inputs = 1
246                                 multi_tuner_slot_base = -1
247                                 multi_tuner_slot_channel = 0
248
249                         slot_id = sl.slot
250
251                         for num in xrange(inputs):
252                                 if multi_tuner_slot_base != -1:
253                                         slot = nim_slots[multi_tuner_slot_base+num]
254                                         input = num
255                                 else:
256                                         slot = sl
257                                         input = -1
258
259                                 nim = slot.config
260
261                                 if slot.isEnabled("DVB-S"):
262
263                                         if multi_tuner_slot_base != -1:
264                                                 Log.i("Slot " + str(slot.slot) + " Channel " + str(sl.channel) + " Input " + chr(ord('A')+num) + " Configmode " + str(nim.sat.configMode.value))
265                                         else:
266                                                 Log.i("Slot " + str(slot_id) + " Configmode " + str(nim.sat.configMode.value))
267
268                                         if nim.sat.configMode.value in ( "loopthrough", "satposdepends", "nothing" ):
269                                                 pass
270                                         else:
271                                                 slotLinked = False
272                                                 if nim.sat.configMode.value == "equal":
273                                                         pass
274                                                 elif nim.sat.configMode.value == "simple":              #simple config
275                                                         Log.i("DiSEqC Mode " + str(nim.diseqcMode.value))
276                                                         if nim.diseqcMode.value == "single":                    #single
277                                                                 if nim.simpleSingleSendDiSEqC.value:
278                                                                         self.addLNBSimple(sec, slotid = slot_id, input = input, orbpos = nim.diseqcA.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.AA, diseqc13V = nim.diseqc13V.value, degreePerSecond = nim.degreePerSecond.float)
279                                                                 else:
280                                                                         self.addLNBSimple(sec, slotid = slot_id, input = input, orbpos = nim.diseqcA.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.NONE, diseqcpos = diseqcParam.SENDNO, diseqc13V = nim.diseqc13V.value, degreePerSecond = nim.degreePerSecond.float)
281                                                         elif nim.diseqcMode.value == "toneburst_a_b":           #Toneburst A/B
282                                                                 self.addLNBSimple(sec, slotid = slot_id, input = input, orbpos = nim.diseqcA.orbital_position, toneburstmode = diseqcParam.A, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.SENDNO, diseqc13V = nim.diseqc13V.value, degreePerSecond = nim.degreePerSecond.float)
283                                                                 self.addLNBSimple(sec, slotid = slot_id, input = input, orbpos = nim.diseqcB.orbital_position, toneburstmode = diseqcParam.B, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.SENDNO, diseqc13V = nim.diseqc13V.value, degreePerSecond = nim.degreePerSecond.float)
284                                                         elif nim.diseqcMode.value == "diseqc_a_b":              #DiSEqC A/B
285                                                                 fastDiSEqC = nim.simpleDiSEqCOnlyOnSatChange.value
286                                                                 setVoltageTone = nim.simpleDiSEqCSetVoltageTone.value
287                                                                 self.addLNBSimple(sec, slotid = slot_id, input = input, orbpos = nim.diseqcA.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.AA, fastDiSEqC = fastDiSEqC, setVoltageTone = setVoltageTone, diseqc13V = nim.diseqc13V.value, degreePerSecond = nim.degreePerSecond.float)
288                                                                 self.addLNBSimple(sec, slotid = slot_id, input = input, orbpos = nim.diseqcB.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.AB, fastDiSEqC = fastDiSEqC, setVoltageTone = setVoltageTone, diseqc13V = nim.diseqc13V.value, degreePerSecond = nim.degreePerSecond.float)
289                                                         elif nim.diseqcMode.value == "diseqc_a_b_c_d":          #DiSEqC A/B/C/D
290                                                                 fastDiSEqC = nim.simpleDiSEqCOnlyOnSatChange.value
291                                                                 setVoltageTone = nim.simpleDiSEqCSetVoltageTone.value
292                                                                 self.addLNBSimple(sec, slotid = slot_id, input = input, orbpos = nim.diseqcA.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.AA, fastDiSEqC = fastDiSEqC, setVoltageTone = setVoltageTone, diseqc13V = nim.diseqc13V.value, degreePerSecond = nim.degreePerSecond.float)
293                                                                 self.addLNBSimple(sec, slotid = slot_id, input = input, orbpos = nim.diseqcB.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.AB, fastDiSEqC = fastDiSEqC, setVoltageTone = setVoltageTone, diseqc13V = nim.diseqc13V.value, degreePerSecond = nim.degreePerSecond.float)
294                                                                 self.addLNBSimple(sec, slotid = slot_id, input = input, orbpos = nim.diseqcC.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.BA, fastDiSEqC = fastDiSEqC, setVoltageTone = setVoltageTone, diseqc13V = nim.diseqc13V.value, degreePerSecond = nim.degreePerSecond.float)
295                                                                 self.addLNBSimple(sec, slotid = slot_id, input = input, orbpos = nim.diseqcD.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.BB, fastDiSEqC = fastDiSEqC, setVoltageTone = setVoltageTone, diseqc13V = nim.diseqc13V.value, degreePerSecond = nim.degreePerSecond.float)
296                                                         elif nim.diseqcMode.value == "positioner":              #Positioner
297                                                                 if nim.latitudeOrientation.value == "north":
298                                                                         laValue = rotorParam.NORTH
299                                                                 else:
300                                                                         laValue = rotorParam.SOUTH
301                                                                 if nim.longitudeOrientation.value == "east":
302                                                                         loValue = rotorParam.EAST
303                                                                 else:
304                                                                         loValue = rotorParam.WEST
305                                                                 inputPowerDelta=nim.powerThreshold.value
306                                                                 useInputPower=False
307                                                                 turning_speed=0
308                                                                 if nim.powerMeasurement.value:
309                                                                         useInputPower=True
310                                                                         turn_speed_dict = { "fast": rotorParam.FAST, "slow": rotorParam.SLOW }
311                                                                         if turn_speed_dict.has_key(nim.turningSpeed.value):
312                                                                                 turning_speed = turn_speed_dict[nim.turningSpeed.value]
313                                                                         else:
314                                                                                 beg_time = localtime(nim.fastTurningBegin.value)
315                                                                                 end_time = localtime(nim.fastTurningEnd.value)
316                                                                                 turning_speed = ((beg_time.tm_hour+1) * 60 + beg_time.tm_min + 1) << 16
317                                                                                 turning_speed |= (end_time.tm_hour+1) * 60 + end_time.tm_min + 1
318                                                                 self.addLNBSimple(sec, slotid = slot_id, input = input, diseqcmode = 3,
319                                                                         longitude = nim.longitude.float,
320                                                                         loDirection = loValue,
321                                                                         latitude = nim.latitude.float,
322                                                                         laDirection = laValue,
323                                                                         turningSpeed = turning_speed,
324                                                                         useInputPower = useInputPower,
325                                                                         inputPowerDelta = inputPowerDelta,
326                                                                         diseqc13V = nim.diseqc13V.value)
327                                                 elif nim.sat.configMode.value == "advanced": #advanced config
328                                                         slotLinked = self.updateAdvanced(sec, slot.slot, input, slot_id if inputs > 1 else None)
329                                                 if not slotLinked:
330                                                         sec.setSlotNotLinked(slot_id)
331                 Log.i("sec config completed")
332
333         def updateAdvanced(self, sec, slotid, input, slotid_child=None):
334
335                 if slotid_child is not None:
336                         channel = slotid_child - slotid
337                         #print "updateAdvanced", slotid, "hw input", input, "channel", channel
338
339                 slotLinked = False
340                 try:
341                         if slotid_child is None and config.Nims[slotid].advanced.unicableconnected is not None:
342                                 if config.Nims[slotid].advanced.unicableconnected.value:
343                                         self.linkNIMs(sec, slotid, int(config.Nims[slotid].advanced.unicableconnectedTo.value))
344                                         connto = self.getRoot(slotid, int(config.Nims[slotid].advanced.unicableconnectedTo.value))
345                                         if not self.linked.has_key(connto):
346                                                 self.linked[connto] = []
347                                         self.linked[connto].append(slotid)
348                                         slotLinked = True
349                                 else:
350                                         config.Nims[slotid].advanced.unicableconnectedTo.save_forced = False
351                 except:
352                         pass
353
354                 lnbSat = {}
355                 for x in range(1,37):
356                         lnbSat[x] = []
357
358                 #wildcard for all satellites ( for rotor )
359                 for x in range(3601, 3605):
360                         lnb = int(config.Nims[slotid].advanced.sat[x].lnb.value)
361                         if lnb != 0:
362                                 Log.i("add rotor satellites to lnb" + str(lnb))
363                                 for x in self.NimManager.satList:
364                                         lnbSat[lnb].append(x[0])
365
366                 for x in self.NimManager.satList:
367                         lnb = int(config.Nims[slotid].advanced.sat[x[0]].lnb.value)
368                         if lnb != 0:
369                                 Log.i("add " + str(x[0]) + " to " + str(lnb))
370                                 lnbSat[lnb].append(x[0])
371
372                 for x in range(1,37):
373                         if len(lnbSat[x]) > 0:
374                                 currLnb = config.Nims[slotid].advanced.lnb[x]
375                                 scr_idx = -1
376
377                                 if currLnb.lof.value == "unicable" and slotid_child is not None:
378                                         if currLnb.unicable.value == "unicable_user":
379                                                 Log.i("warning Slot " + str(slotid) + " Channel " + str(channel) + " LNB " + str(x) + " unicable user defined is not yet working with multi channel tuners... skip")
380                                                 continue
381                                         elif currLnb.unicable.value == "unicable_lnb":
382                                                 manufacturer = currLnb.unicableLnb
383                                         else:
384                                                 manufacturer = currLnb.unicableMatrix
385
386                                         vcos = manufacturer.scrs.value
387                                         if len(vcos) <= channel:
388                                                 Log.i("warning Slot " + str(slotid) + " Channel " + str(channel) + " LNB " + str(x) + " not enough SCRs configured... no unicable possible with this channel... skip")
389                                                 continue
390
391                                         vco = vcos[channel]
392
393                                         cnt = 0
394                                         for v in manufacturer.vco:
395                                                 if v.value == vco:
396                                                         scr_idx = cnt
397                                                         break
398                                                 cnt += 1
399
400                                         if scr_idx == -1:
401                                                 Log.i("warning Slot " + str(slotid) + " Channel " + str(channel) + " LNB " + str(x) + " could not found SCR IDX for VCO " + str(vco) + " ... no unicable possible with this channel... skip")
402                                                 continue
403
404                                         Log.i("use SCR" + str(scr_idx+1) + " " + str(vco) + "Mhz")
405
406                                 sec.addLNB()
407                                 sec.setLNBTunerInput(input)
408
409                                 if x < 33:
410                                         sec.setLNBNum(x)
411
412                                 if slotid_child is not None:
413                                         tunermask = 1 << slotid_child
414                                 else:
415                                         tunermask = 1 << slotid
416
417                                         if self.equal.has_key(slotid):
418                                                 for slot in self.equal[slotid]:
419                                                         tunermask |= (1 << slot)
420                                         if self.linked.has_key(slotid):
421                                                 for slot in self.linked[slotid]:
422                                                         tunermask |= (1 << slot)
423
424                                 if currLnb.lof.value != "unicable":
425                                         sec.setLNBSatCR(-1)
426
427                                 if currLnb.lof.value == "universal_lnb":
428                                         sec.setLNBLOFL(9750000)
429                                         sec.setLNBLOFH(10600000)
430                                         sec.setLNBThreshold(11700000)
431                                 elif currLnb.lof.value == "unicable":
432
433                                         def setupUnicable(configManufacturer, ProductDict, scr_idx):
434                                                 manufacturer = ProductDict
435                                                 if scr_idx == -1:
436                                                         scr_idx = manufacturer.scr.index
437
438                                                 sec.setLNBSatCR(scr_idx)
439                                                 sec.setLNBSatCRvco(manufacturer.vco[scr_idx].value * 1000)
440                                                 sec.setLNBSatCRpositions(manufacturer.positions[0].value)
441                                                 sec.setLNBSatCRmode(manufacturer.mode.value)
442                                                 sec.setLNBLOFL(manufacturer.lofl[0].value * 1000)
443                                                 sec.setLNBLOFH(manufacturer.lofh[0].value * 1000)
444                                                 sec.setLNBThreshold(manufacturer.loft[0].value * 1000)
445
446                                         if currLnb.unicable.value == "unicable_user":
447                                                 sec.setLNBLOFL(currLnb.lofl.value * 1000)
448                                                 sec.setLNBLOFH(currLnb.lofh.value * 1000)
449                                                 sec.setLNBThreshold(currLnb.threshold.value * 1000)
450                                                 sec.setLNBSatCR(currLnb.satcruser.index)
451                                                 sec.setLNBSatCRvco(currLnb.satcrvcouser[currLnb.satcruser.index].value*1000)
452                                                 sec.setLNBSatCRpositions(1) # HACK
453                                                 sec.setLNBSatCRmode(currLnb.satcruser_mode.index)
454                                         elif currLnb.unicable.value == "unicable_matrix":
455                                                 setupUnicable(currLnb.unicableMatrix.manufacturer, currLnb.unicableMatrix, scr_idx)
456                                         elif currLnb.unicable.value == "unicable_lnb":
457                                                 setupUnicable(currLnb.unicableLnb.manufacturer, currLnb.unicableLnb, scr_idx)
458                                         if currLnb.unicable_use_pin.value:
459                                                 sec.setLNBSatCRpin(currLnb.unicable_pin.value)
460                                         else:
461                                                 sec.setLNBSatCRpin(-1)
462                                 elif currLnb.lof.value == "c_band":
463                                         sec.setLNBLOFL(5150000)
464                                         sec.setLNBLOFH(5150000)
465                                         sec.setLNBThreshold(5150000)
466                                 elif currLnb.lof.value == "user_defined":
467                                         sec.setLNBLOFL(currLnb.lofl.value * 1000)
468                                         sec.setLNBLOFH(currLnb.lofh.value * 1000)
469                                         sec.setLNBThreshold(currLnb.threshold.value * 1000)
470
471 #                               if currLnb.output_12v.value == "0V":
472 #                                       pass # nyi in drivers
473 #                               elif currLnb.output_12v.value == "12V":
474 #                                       pass # nyi in drivers
475
476                                 if currLnb.increased_voltage.value:
477                                         sec.setLNBIncreasedVoltage(True)
478                                 else:
479                                         sec.setLNBIncreasedVoltage(False)
480
481                                 dm = currLnb.diseqcMode.value
482                                 if dm == "none":
483                                         sec.setDiSEqCMode(diseqcParam.NONE)
484                                 elif dm == "1_0":
485                                         sec.setDiSEqCMode(diseqcParam.V1_0)
486                                 elif dm == "1_1":
487                                         sec.setDiSEqCMode(diseqcParam.V1_1)
488                                 elif dm == "1_2":
489                                         sec.setDiSEqCMode(diseqcParam.V1_2)
490
491                                         if self.satposdepends.has_key(slotid):
492                                                 for slot in self.satposdepends[slotid]:
493                                                         tunermask |= (1 << slot)
494
495                                 if dm != "none":
496                                         if currLnb.toneburst.value == "none":
497                                                 sec.setToneburst(diseqcParam.NO)
498                                         elif currLnb.toneburst.value == "A":
499                                                 sec.setToneburst(diseqcParam.A)
500                                         elif currLnb.toneburst.value == "B":
501                                                 sec.setToneburst(diseqcParam.B)
502
503                                         # Committed Diseqc Command
504                                         cdc = currLnb.commitedDiseqcCommand.value
505
506                                         c = { "none": diseqcParam.SENDNO,
507                                                 "AA": diseqcParam.AA,
508                                                 "AB": diseqcParam.AB,
509                                                 "BA": diseqcParam.BA,
510                                                 "BB": diseqcParam.BB }
511
512                                         if c.has_key(cdc):
513                                                 sec.setCommittedCommand(c[cdc])
514                                         else:
515                                                 sec.setCommittedCommand(long(cdc))
516
517                                         sec.setFastDiSEqC(currLnb.fastDiseqc.value)
518
519                                         sec.setSeqRepeat(currLnb.sequenceRepeat.value)
520
521                                         if currLnb.diseqcMode.value == "1_0":
522                                                 currCO = currLnb.commandOrder1_0.value
523                                                 sec.setRepeats(0)
524                                         else:
525                                                 currCO = currLnb.commandOrder.value
526
527                                                 udc = int(currLnb.uncommittedDiseqcCommand.value)
528                                                 if udc > 0:
529                                                         sec.setUncommittedCommand(0xF0|(udc-1))
530                                                 else:
531                                                         sec.setUncommittedCommand(0) # SENDNO
532
533                                                 sec.setRepeats({"none": 0, "one": 1, "two": 2, "three": 3}[currLnb.diseqcRepeats.value])
534
535                                         # 0 "committed, toneburst",
536                                         # 1 "toneburst, committed",
537                                         # 2 "committed, uncommitted, toneburst",
538                                         # 3 "toneburst, committed, uncommitted",
539                                         # 4 "uncommitted, committed, toneburst"
540                                         # 5 "toneburst, uncommitted, commmitted"
541                                         order_map = {"ct": 0, "tc": 1, "cut": 2, "tcu": 3, "uct": 4, "tuc": 5}
542                                         sec.setCommandOrder(order_map[currCO])
543
544                                 if dm == "1_2":
545                                         latitude = currLnb.latitude.float
546                                         sec.setLatitude(latitude)
547                                         longitude = currLnb.longitude.float
548                                         sec.setLongitude(longitude)
549                                         if currLnb.latitudeOrientation.value == "north":
550                                                 sec.setLaDirection(rotorParam.NORTH)
551                                         else:
552                                                 sec.setLaDirection(rotorParam.SOUTH)
553                                         if currLnb.longitudeOrientation.value == "east":
554                                                 sec.setLoDirection(rotorParam.EAST)
555                                         else:
556                                                 sec.setLoDirection(rotorParam.WEST)
557
558                                         if currLnb.powerMeasurement.value:
559                                                 sec.setUseInputpower(True)
560                                                 sec.setInputpowerDelta(currLnb.powerThreshold.value)
561                                                 turn_speed_dict = { "fast": rotorParam.FAST, "slow": rotorParam.SLOW }
562                                                 if turn_speed_dict.has_key(currLnb.turningSpeed.value):
563                                                         turning_speed = turn_speed_dict[currLnb.turningSpeed.value]
564                                                 else:
565                                                         beg_time = localtime(currLnb.fastTurningBegin.value)
566                                                         end_time = localtime(currLnb.fastTurningEnd.value)
567                                                         turning_speed = ((beg_time.tm_hour + 1) * 60 + beg_time.tm_min + 1) << 16
568                                                         turning_speed |= (end_time.tm_hour + 1) * 60 + end_time.tm_min + 1
569                                                 sec.setRotorTurningSpeed(turning_speed)
570                                         else:
571                                                 sec.setUseInputpower(False)
572                                                 sec.setDegreePerSecond(int(currLnb.degreePerSecond.float*10))
573
574                                 sec.setLNBSlotMask(tunermask)
575
576                                 sec.setLNBPrio(int(currLnb.prio.value))
577
578                                 # finally add the orbital positions
579                                 for y in lnbSat[x]:
580                                         self.addSatellite(sec, y)
581                                         if x > 32:
582                                                 satpos = x > 32 and (3604-(36 - x)) or y
583                                         else:
584                                                 satpos = y
585                                         currSat = config.Nims[slotid].advanced.sat[satpos]
586                                         if currSat.voltage.value == "polarization":
587                                                 if config.Nims[slotid].diseqc13V.value:
588                                                         sec.setVoltageMode(switchParam.HV_13)
589                                                 else:
590                                                         sec.setVoltageMode(switchParam.HV)
591                                         elif currSat.voltage.value == "13V":
592                                                 sec.setVoltageMode(switchParam._14V)
593                                         elif currSat.voltage.value == "18V":
594                                                 sec.setVoltageMode(switchParam._18V)
595
596                                         if currSat.tonemode.value == "band":
597                                                 sec.setToneMode(switchParam.HILO)
598                                         elif currSat.tonemode.value == "on":
599                                                 sec.setToneMode(switchParam.ON)
600                                         elif currSat.tonemode.value == "off":
601                                                 sec.setToneMode(switchParam.OFF)
602
603                                         if not currSat.usals.value and x < 34:
604                                                 sec.setRotorPosNum(currSat.rotorposition.value)
605                                         else:
606                                                 sec.setRotorPosNum(0) #USALS
607                 return slotLinked
608
609         def __init__(self, nimmgr):
610                 self.NimManager = nimmgr
611                 self.configuredSatellites = set()
612                 self.update()
613
614 class NIM(object):
615         SUPPORTED_TYPES = ("DVB-S", "DVB-C", "DVB-T", "DVB-T2", "DVB-S2", None)
616
617         def __init__(self, slot, type, description, has_outputs = True, internally_connectable = None, multi_type = {}, frontend_id = None, i2c = None, is_empty = False, input_name = None, inputs = None):
618                 self.slot = slot
619                 if type not in NIM.SUPPORTED_TYPES:
620                         print "warning: unknown NIM type %s, not using." % type
621                         type = None
622
623                 self.description = description
624                 self.has_outputs = has_outputs
625                 self.internally_connectable = internally_connectable
626                 if type and not multi_type:
627                         multi_type = { '0' : type }
628                 self._types = multi_type
629                 self.i2c = i2c
630                 self.frontend_id = frontend_id
631                 self.__is_empty = is_empty
632                 self.input_name = input_name
633                 try:
634                         self.channel = int(input_name[1]) - 1
635                 except:
636                         self.channel = 0
637                 self.can_auto_fec_s2 = self.description != "Alps BSBE2"
638                 self.can_modulation_auto = len(multi_type) > 1 or self.description.startswith("Si216")
639                 self.can_pls_s2 = self.description == "Si2166D"
640                 self.can_multistream_s2 = self.can_pls_s2
641                 self.can_s_s2_auto_delsys = self.description.startswith("Si216")
642                 self.inputs = inputs
643
644         def isEnabled(self, what):
645                 ret = self.isCompatible(what)
646                 if ret:
647                         if what in ('DVB-S', 'DVB-S2'): 
648                                 return self.config.sat.configMode.value != "nothing"
649                         elif what in ('DVB-T', 'DVB-T2'): 
650                                 return self.config.terrest.configMode.value != "nothing"
651                         elif what in ('DVB-C'): 
652                                 return self.config.cable.configMode.value != "nothing"
653                 return ret
654
655         def isCompatible(self, what):
656                 if not self.isSupported():
657                         return False
658                 compatible = {
659                                 None: (None,),
660                                 "DVB-S": ("DVB-S", None),
661                                 "DVB-C": ("DVB-C", None),
662                                 "DVB-T": ("DVB-T", None),
663                                 "DVB-T2": ("DVB-T", "DVB-T2", None),
664                                 "DVB-S2": ("DVB-S", "DVB-S2", None)
665                         }
666                 for ntype in self._types.itervalues():
667                         if what in compatible[ntype]:
668                                 return True
669                 return False
670
671         def getTypes(self):
672                 return self._types
673         types = property(getTypes)
674
675         def getType(self):
676                 if not self._types:
677                         return None
678                 type = self._types.values()[0]
679                 if len(self._types) > 1:
680                         import traceback
681                         print "\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\nNIM Slot", self.getSlotInputName(), "supports multiple types", self._types, "\nthis function is deprecated and just for backward compatibility it should not be used anymore\nplease report to plugin author... ", type, "is returned for this nim now"
682                         traceback.print_stack(limit = 2)
683                 return type
684         type = property(getType)
685
686         def connectableTo(self):
687                 connectable = {
688                                 "DVB-S": ("DVB-S", "DVB-S2"),
689                                 "DVB-C": ("DVB-C",),
690                                 "DVB-T": ("DVB-T",),
691                                 "DVB-T2": ("DVB-T", "DVB-T2"),
692                                 "DVB-S2": ("DVB-S", "DVB-S2")
693                         }
694                 connectables = []
695                 for ntype in self._types.itervalues():
696                         if ntype in connectable[ntype]:
697                                 connectables.append(ntype)
698                 return connectables
699
700         def getSlotInputName(self):
701                 name = self.input_name
702                 if name is None:
703                         name = chr(ord('A') + self.slot)
704                 return name
705
706         slot_input_name = property(getSlotInputName)
707
708         def getSlotName(self):
709                 # get a friendly description for a slot name.
710                 # we name them "Tuner A/B/C/...", because that's what's usually written on the back
711                 # of the device.
712                 descr = _("Tuner ")
713                 return descr + self.getSlotInputName()
714
715         slot_name = property(getSlotName)
716
717         def getSlotID(self):
718                 return chr(ord('A') + self.slot)
719
720         def getI2C(self):
721                 return self.i2c
722
723         def hasOutputs(self):
724                 return self.has_outputs
725
726         def internallyConnectableTo(self):
727                 return self.internally_connectable
728
729         def setInternalLink(self):
730                 if self.internally_connectable is not None:
731                         print "setting internal link on frontend id", self.frontend_id
732                         with open("/proc/stb/frontend/%d/rf_switch" % self.frontend_id, "w") as f:
733                                 f.write("internal")
734
735         def removeInternalLink(self):
736                 if self.internally_connectable is not None:
737                         print "removing internal link on frontend id", self.frontend_id
738                         with open("/proc/stb/frontend/%d/rf_switch" % self.frontend_id, "w") as f:
739                                 f.write("external")
740
741         def isMultiType(self):
742                 return (len(self._types) > 1)
743
744         def isEmpty(self):
745                 return self.__is_empty
746
747         # empty tuners are supported!
748         def isSupported(self):
749                 return (self.frontend_id is not None) or self.__is_empty
750
751         # returns dict {<slotid>: <type>}
752         def getMultiTypeList(self):
753                 return self._types
754
755         slot_id = property(getSlotID)
756
757         def getFriendlyType(self):
758                 return _("empty") if not self._types else " / ".join(self._types.values())
759
760         friendly_type = property(getFriendlyType)
761
762         def getFriendlyFullDescription(self):
763                 nim_text = self.slot_name + ": "
764
765                 if self.empty:
766                         nim_text += _("(empty)")
767                 elif not self.isSupported():
768                         nim_text += self.description + " (" + _("not supported") + ")"
769                 else:
770                         nim_text += self.description + " (" + self.friendly_type + ")"
771
772                 return nim_text
773
774         friendly_full_description = property(getFriendlyFullDescription)
775         config = property(lambda self: config.Nims[self.slot])
776         empty = property(lambda self: not self._types)
777
778 class NimManager:
779         config_mode_str = {
780                 "nothing" : _("inactive"),
781                 "multi" : _("multiple"),
782                 "enabled" : _("active"),
783                 "simple" : _("simple"),
784                 "advanced" : _("advanced"),
785                 "equal" : _("equal to"),
786                 "satposdepends" : _("second cable of motorized LNB"),
787                 "loopthrough" : "", # description is dynamically generated by connectedToChanged function (InitNimManager)
788                 }
789
790         def getConfigModeTuple(self, mode):
791                 return (mode, NimManager.config_mode_str[mode])
792
793         def getConfiguredSats(self):
794                 if self.sec:
795                         return self.sec.getConfiguredSats()
796                 else:
797                         return set()
798
799         def getTransponders(self, pos):
800                 if self.transponders.has_key(pos):
801                         return self.transponders[pos]
802                 else:
803                         return []
804
805         def getTranspondersCable(self, nim):
806                 nimConfig = config.Nims[nim]
807                 if nimConfig.cable.configMode.value != "nothing" and nimConfig.cable.scan_type.value == "provider":
808                         return self.transponderscable[self.cablesList[nimConfig.cable.scan_provider.index][0]]
809                 return [ ]
810
811         def getTranspondersTerrestrial(self, region):
812                 return self.transpondersterrestrial[region]
813
814         def getCableDescription(self, nim):
815                 return self.cablesList[config.Nims[nim].scan_provider.index][0]
816
817         def getCableFlags(self, nim):
818                 return self.cablesList[config.Nims[nim].scan_provider.index][1]
819
820         def getTerrestrialDescription(self, nim):
821                 return self.terrestrialsList[config.Nims[nim].terrest.provider.index][0]
822
823         def getTerrestrialFlags(self, nim):
824                 return self.terrestrialsList[config.Nims[nim].terrest.provider.index][1]
825
826         def getSatDescription(self, pos):
827                 return self.satellites[pos]
828
829         def sortFunc(self, x):
830                 orbpos = x[0]
831                 if orbpos > 1800:
832                         return orbpos - 3600
833                 else:
834                         return orbpos + 1800
835
836         def readTransponders(self):
837                 # read initial networks from file. we only read files which we are interested in,
838                 # which means only these where a compatible tuner exists.
839                 self.satellites = { }
840                 self.transponders = { }
841                 self.transponderscable = { }
842                 self.transpondersterrestrial = { }
843                 db = eDVBDB.getInstance()
844                 if self.hasNimType("DVB-S"):
845                         print "Reading satellites.xml"
846                         db.readSatellites(self.satList, self.satellites, self.transponders)
847                         self.satList.sort(key = self.sortFunc) # sort by orbpos
848                         #print "SATLIST", self.satList
849                         #print "SATS", self.satellites
850                         #print "TRANSPONDERS", self.transponders
851
852                 if self.hasNimType("DVB-C"):
853                         print "Reading cables.xml"
854                         db.readCables(self.cablesList, self.transponderscable)
855 #                       print "CABLIST", self.cablesList
856 #                       print "TRANSPONDERS", self.transponders
857
858                 if self.hasNimType("DVB-T"):
859                         print "Reading terrestrial.xml"
860                         db.readTerrestrials(self.terrestrialsList, self.transpondersterrestrial)
861 #                       print "TERLIST", self.terrestrialsList
862 #                       print "TRANSPONDERS", self.transpondersterrestrial
863
864         def enumerateNIMs(self):
865                 # enum available NIMs. This is currently very dreambox-centric and uses the /proc/bus/nim_sockets interface.
866                 # the result will be stored into nim_slots.
867                 # the content of /proc/bus/nim_sockets looks like:
868                 # NIM Socket 0:
869                 #          Type: DVB-S
870                 #          Name: BCM4501 DVB-S2 NIM (internal)
871                 # NIM Socket 1:
872                 #          Type: DVB-S
873                 #          Name: BCM4501 DVB-S2 NIM (internal)
874                 # NIM Socket 2:
875                 #          Type: DVB-T
876                 #          Name: Philips TU1216
877                 # NIM Socket 3:
878                 #          Type: DVB-S
879                 #          Name: Alps BSBE1 702A
880
881                 #
882                 # Type will be either "DVB-S", "DVB-S2", "DVB-T", "DVB-C", "DVB-T2" or None.
883
884                 # nim_slots is an array which has exactly one entry for each slot, even for empty ones.
885                 self.nim_slots = [ ]
886
887                 nimfile = tryOpen("/proc/bus/nim_sockets")
888
889                 if nimfile is None:
890                         return
891
892                 current_slot = None
893
894                 entries = {}
895                 for line in nimfile.readlines():
896                         if line == "":
897                                 break
898                         if line.strip().startswith("NIM Socket"):
899                                 parts = line.strip().split(" ")
900                                 current_slot = int(parts[2][:-1])
901                                 entries[current_slot] = {}
902                         elif line.strip().startswith("Type:"):
903                                 entries[current_slot]["type"] = str(line.strip()[6:])
904                                 entries[current_slot]["isempty"] = False
905                         elif line.strip().startswith("Input_Name:"):
906                                 entries[current_slot]["input_name"] = str(line.strip()[12:])
907                         elif line.strip().startswith("Name:"):
908                                 entries[current_slot]["name"] = str(line.strip()[6:])
909                                 entries[current_slot]["isempty"] = False
910                         elif line.strip().startswith("Has_Outputs:"):
911                                 input = str(line.strip()[len("Has_Outputs:") + 1:])
912                                 entries[current_slot]["has_outputs"] = (input == "yes")
913                         elif line.strip().startswith("Internally_Connectable:"):
914                                 input = int(line.strip()[len("Internally_Connectable:") + 1:])
915                                 entries[current_slot]["internally_connectable"] = input
916                         elif line.strip().startswith("Frontend_Device:"):
917                                 input = int(line.strip()[len("Frontend_Device:") + 1:])
918                                 entries[current_slot]["frontend_device"] = input
919                         elif  line.strip().startswith("Mode"):
920                                 # "Mode 0: DVB-T" -> ["Mode 0", " DVB-T"]
921                                 split = line.strip().split(":")
922                                 # "Mode 0" -> ["Mode, "0"]
923                                 split2 = split[0].split(" ")
924                                 modes = entries[current_slot].get("multi_type", {})
925                                 modes[split2[1]] = split[1].strip()
926                                 entries[current_slot]["multi_type"] = modes
927                         elif line.strip().startswith("I2C_Device:"):
928                                 input = int(line.strip()[len("I2C_Device:") + 1:])
929                                 entries[current_slot]["i2c"] = input
930                         elif line.strip().startswith("empty"):
931                                 entries[current_slot]["type"] = None
932                                 entries[current_slot]["name"] = _("N/A")
933                                 entries[current_slot]["isempty"] = True
934                 nimfile.close()
935
936                 channel = -1
937                 for id, entry in entries.items():
938                         if not (entry.has_key("name") and entry.has_key("type")):
939                                 entry["name"] =  _("N/A")
940                                 entry["type"] = None
941                         if not (entry.has_key("i2c")):
942                                 entry["i2c"] = None
943                         entry["inputs"] = None
944                         if entry.has_key("frontend_device"): # check if internally connectable
945                                 if exists("/proc/stb/frontend/%d/rf_switch" % entry["frontend_device"]):
946                                         entry["internally_connectable"] = id -1 if entries[id]["input_name"][-1] == '2' else id + 1
947                                 else:
948                                         entry["internally_connectable"] = None
949                                 inputChoicesFile = tryOpen("/proc/stb/frontend/%d/input_choices" % entry["frontend_device"])
950                                 if inputChoicesFile:
951                                         choices = inputChoicesFile.readline()
952                                         if choices:
953                                                 entry["inputs"] = choices[:-1].split(' ')
954                         else:
955                                 entry["frontend_device"] = entry["internally_connectable"] = None
956                         if not (entry.has_key("multi_type")):
957                                 entry["multi_type"] = {}
958                         nim = NIM(slot = id, description = entry["name"], type = entry["type"], internally_connectable = entry["internally_connectable"], multi_type = entry["multi_type"], frontend_id = entry["frontend_device"], i2c = entry["i2c"], is_empty = entry["isempty"], input_name = entry.get("input_name", None), inputs = entry["inputs"] )
959                         # calculate and set number of channels
960                         if channel != -1 and nim.channel <= channel:
961                                 slot_start = id - 1 - channel
962                                 for slot in xrange(slot_start, slot_start + channel + 1):
963                                         self.nim_slots[slot].channels = channel + 1
964                         channel = nim.channel
965                         self.nim_slots.append(nim)
966                 # set number of channels for last slot
967                 slot_start = id - channel
968                 for slot in xrange(slot_start, slot_start + channel + 1):
969                         self.nim_slots[slot].channels = channel + 1
970
971         def hasNimType(self, chktype):
972                 ret = False
973                 for slot in self.nim_slots:
974                         if slot.isCompatible(chktype):
975                                 return True
976                 return ret
977
978         def getNimType(self, slotid):
979                 return self.nim_slots[slotid].type
980
981         def getNimTypes(self, slotid):
982                 return self.nim_slots[slotid].types.values()
983
984         def getNimDescription(self, slotid):
985                 return self.nim_slots[slotid].friendly_full_description
986
987         def getNimName(self, slotid):
988                 return self.nim_slots[slotid].description
989
990         def getNimSlotInputName(self, slotid):
991                 # returns just "A", "B", ...
992                 return self.nim_slots[slotid].slot_input_name
993
994         def getNimSlotName(self, slotid):
995                 # returns a friendly description string ("Tuner A", "Tuner B" etc.)
996                 return self.nim_slots[slotid].slot_name
997
998         def getNim(self, slotid):
999                 return self.nim_slots[slotid]
1000
1001         def getI2CDevice(self, slotid):
1002                 return self.nim_slots[slotid].getI2C()
1003
1004         def getNimListOfType(self, type, exception = -1):
1005                 # returns a list of indexes for NIMs compatible to the given type, except for 'exception'
1006                 list = []
1007                 for x in self.nim_slots:
1008                         if x.isCompatible(type) and x.slot != exception:
1009                                 list.append(x.slot)
1010                 return list
1011
1012         def getNimListForSlot(self, slotid):
1013                 nimList = []
1014                 types = self.getNimTypes(slotid)
1015                 if "DVB-S2" in types:
1016                         nimList.extend(self.getNimListOfType("DVB-S", slotid))
1017                 elif type == "DVB-T2":
1018                         nimList.extend(self.getNimListOfType("DVB-T", slotid))
1019                 return nimList
1020
1021         def __init__(self):
1022                 self.satList = [ ]
1023                 self.cablesList = []
1024                 self.terrestrialsList = []
1025                 self.sec = None
1026                 self.enumerateNIMs()
1027                 self.readTransponders()
1028
1029         # get a list with the friendly full description
1030         def nimList(self):
1031                 list = [ ]
1032                 for slot in self.nim_slots:
1033                         if slot.inputs is None or slot.channel == 0:
1034                                 list.append(slot.friendly_full_description)
1035                 return list
1036
1037         def getSlotCount(self):
1038                 return len(self.nim_slots)
1039
1040         def hasOutputs(self, slotid):
1041                 return self.nim_slots[slotid].hasOutputs()
1042
1043         def nimInternallyConnectableTo(self, slotid):
1044                 return self.nim_slots[slotid].internallyConnectableTo()
1045
1046         def nimRemoveInternalLink(self, slotid):
1047                 self.nim_slots[slotid].removeInternalLink()
1048
1049         def canConnectTo(self, slotid):
1050                 slots = []
1051
1052                 internally_connectable = self.nimInternallyConnectableTo(slotid)
1053                 if internally_connectable is not None:
1054                         slots.append(internally_connectable)
1055                 for type in self.nim_slots[slotid].connectableTo(): 
1056                         for slot in self.getNimListOfType(type, exception = slotid):
1057                                 if self.hasOutputs(slot):
1058                                         slots.append(slot)
1059                 # remove nims, that have a conntectedTo reference on
1060                 for testnim in slots[:]:
1061                         # FIXMEE
1062                         # no support for satpos depends, equal to and loopthough setting for nims with
1063                         # with multiple inputs and multiple channels
1064                         if self.nim_slots[testnim].inputs is not None:
1065                                 slots.remove(testnim)
1066                         else:
1067                                 for nim in self.getNimListOfType("DVB-S", slotid):
1068                                         nimConfig = self.getNimConfig(nim)
1069                                         if nimConfig.content.items.has_key("configMode") and nimConfig.sat.configMode.value == "loopthrough" and int(nimConfig.connectedTo.value) == testnim:
1070                                                 slots.remove(testnim)
1071                                                 break
1072                 slots.sort()
1073                 
1074                 return slots
1075
1076         def canEqualTo(self, slotid):
1077                 nimList = self.getNimListForSlot(slotid)
1078                 for nim in nimList[:]:
1079                         print "canEqualTo slotid", slotid, "nim", nim
1080                         mode = self.getNimConfig(nim)
1081                         # FIXMEE
1082                         # no support for satpos depends, equal to and loopthough setting for nims with
1083                         # with multiple inputs and multiple channels
1084                         if self.nim_slots[nim].inputs is not None or mode.configMode.value == "loopthrough" or mode.configMode.value == "satposdepends":
1085                                 nimList.remove(nim)
1086                 return nimList
1087
1088         def canDependOn(self, slotid):
1089                 positionerList = []
1090                 nimList = self.getNimListForSlot(slotid)
1091                 for nim in nimList[:]:
1092                         mode = self.getNimConfig(nim)
1093                         nimHaveRotor = mode.sat.configMode.value == "simple" and mode.diseqcMode.value == "positioner"
1094                         if not nimHaveRotor and mode.sat.configMode.value == "advanced":
1095                                 for x in range(3601, 3605):
1096                                         lnb = int(mode.advanced.sat[x].lnb.value)
1097                                         if lnb != 0:
1098                                                 nimHaveRotor = True
1099                                                 break
1100                                 if not nimHaveRotor:
1101                                         for sat in mode.advanced.sat.values():
1102                                                 lnb_num = int(sat.lnb.value)
1103                                                 diseqcmode = lnb_num and mode.advanced.lnb[lnb_num].diseqcMode.value or ""
1104                                                 if diseqcmode == "1_2":
1105                                                         nimHaveRotor = True
1106                                                         break
1107                         # FIXMEE
1108                         # no support for satpos depends, equal to and loopthough setting for nims with
1109                         # with multiple inputs and multiple channels
1110                         if nimHaveRotor and self.nim_slots[nim].inputs is None:
1111                                 alreadyConnected = False
1112                                 for testnim in nimList:
1113                                         testmode = self.getNimConfig(testnim)
1114                                         if testmode.sat.configMode.value == "satposdepends" and int(testmode.connectedTo.value) == int(nim):
1115                                                 alreadyConnected = True
1116                                                 break
1117                                 if not alreadyConnected:
1118                                         positionerList.append(nim)
1119                 return positionerList
1120
1121         def getNimConfig(self, slotid):
1122                 return config.Nims[slotid]
1123
1124         def getSatName(self, pos):
1125                 for sat in self.satList:
1126                         if sat[0] == pos:
1127                                 return sat[1]
1128                 return _("N/A")
1129
1130         def getSatList(self):
1131                 return self.satList
1132
1133         # returns True if something is configured to be connected to this nim
1134         # if slotid == -1, returns if something is connected to ANY nim
1135         def somethingConnected(self, slotid = -1):
1136                 if (slotid == -1):
1137                         connected = False
1138                         for id in range(self.getSlotCount()):
1139                                 if self.somethingConnected(id):
1140                                         connected = True
1141                         return connected
1142                 else:
1143                         nim = config.Nims[slotid]
1144                         return (self.nim_slots[slotid].isCompatible("DVB-S") and nim.sat.configMode != "nothing") or \
1145                                 (self.nim_slots[slotid].isCompatible("DVB-C") and nim.cable.configMode != "nothing") or \
1146                                 (self.nim_slots[slotid].isCompatible("DVB-T") and nim.terrest.configMode != "nothing")
1147
1148         def getSatListForNim(self, slotid):
1149                 list = []
1150                 if self.nim_slots[slotid].isEnabled("DVB-S"):
1151                         nim = config.Nims[slotid]
1152                         #print "slotid:", slotid
1153
1154                         #print "self.satellites:", self.satList[config.Nims[slotid].diseqcA.index]
1155                         #print "diseqcA:", config.Nims[slotid].diseqcA.value
1156                         configMode = nim.sat.configMode.value
1157
1158                         if configMode == "equal":
1159                                 slotid = int(nim.connectedTo.value)
1160                                 nim = config.Nims[slotid]
1161                                 configMode = nim.sat.configMode.value
1162                         elif configMode == "loopthrough":
1163                                 slotid = self.sec.getRoot(slotid, int(nim.connectedTo.value))
1164                                 nim = config.Nims[slotid]
1165                                 configMode = nim.sat.configMode.value
1166
1167                         if configMode == "simple":
1168                                 dm = nim.diseqcMode.value
1169                                 if dm in ("single", "toneburst_a_b", "diseqc_a_b", "diseqc_a_b_c_d"):
1170                                         if nim.diseqcA.orbital_position != 3601:
1171                                                 list.append(self.satList[nim.diseqcA.index-1])
1172                                 if dm in ("toneburst_a_b", "diseqc_a_b", "diseqc_a_b_c_d"):
1173                                         if nim.diseqcB.orbital_position != 3601:
1174                                                 list.append(self.satList[nim.diseqcB.index-1])
1175                                 if dm == "diseqc_a_b_c_d":
1176                                         if nim.diseqcC.orbital_position != 3601:
1177                                                 list.append(self.satList[nim.diseqcC.index-1])
1178                                         if nim.diseqcD.orbital_position != 3601:
1179                                                 list.append(self.satList[nim.diseqcD.index-1])
1180                                 if dm == "positioner":
1181                                         for x in self.satList:
1182                                                 list.append(x)
1183                         elif configMode == "advanced":
1184                                 for x in range(3601, 3605):
1185                                         if int(nim.advanced.sat[x].lnb.value) != 0:
1186                                                 for x in self.satList:
1187                                                         list.append(x)
1188                                 if not list:
1189                                         for x in self.satList:
1190                                                 if int(nim.advanced.sat[x[0]].lnb.value) != 0:
1191                                                         list.append(x)
1192                 return list
1193
1194         def getRotorSatListForNim(self, slotid):
1195                 list = []
1196                 if self.nim_slots[slotid].isCompatible("DVB-S"):
1197                         #print "slotid:", slotid
1198                         #print "self.satellites:", self.satList[config.Nims[slotid].diseqcA.value]
1199                         #print "diseqcA:", config.Nims[slotid].diseqcA.value
1200                         configMode = config.Nims[slotid].sat.configMode.value
1201                         if configMode == "simple":
1202                                 if config.Nims[slotid].diseqcMode.value == "positioner":
1203                                         for x in self.satList:
1204                                                 list.append(x)
1205                         elif configMode == "advanced":
1206                                 nim = config.Nims[slotid]
1207                                 for x in range(3601, 3605):
1208                                         if int(nim.advanced.sat[x].lnb.value) != 0:
1209                                                 for x in self.satList:
1210                                                         list.append(x)
1211                                 if not list:
1212                                         for x in self.satList:
1213                                                 lnbnum = int(nim.advanced.sat[x[0]].lnb.value)
1214                                                 if lnbnum != 0:
1215                                                         lnb = nim.advanced.lnb[lnbnum]
1216                                                         if lnb.diseqcMode.value == "1_2":
1217                                                                 list.append(x)
1218                 return list
1219
1220
1221 def InitSecParams():
1222         config.sec = ConfigSubsection()
1223
1224         x = ConfigInteger(default=25, limits = (0, 9999))
1225         x.save_forced = False
1226         x.addNotifier(lambda configElement: secClass.setParam(secClass.DELAY_AFTER_CONT_TONE_DISABLE_BEFORE_DISEQC, configElement.value))
1227         config.sec.delay_after_continuous_tone_disable_before_diseqc = x
1228
1229         x = ConfigInteger(default=10, limits = (0, 9999))
1230         x.save_forced = False
1231         x.addNotifier(lambda configElement: secClass.setParam(secClass.DELAY_AFTER_FINAL_CONT_TONE_CHANGE, configElement.value))
1232         config.sec.delay_after_final_continuous_tone_change = x
1233
1234         x = ConfigInteger(default=10, limits = (0, 9999))
1235         x.save_forced = False
1236         x.addNotifier(lambda configElement: secClass.setParam(secClass.DELAY_AFTER_FINAL_VOLTAGE_CHANGE, configElement.value))
1237         config.sec.delay_after_final_voltage_change = x
1238
1239         x = ConfigInteger(default=120, limits = (0, 9999))
1240         x.save_forced = False
1241         x.addNotifier(lambda configElement: secClass.setParam(secClass.DELAY_BETWEEN_DISEQC_REPEATS, configElement.value))
1242         config.sec.delay_between_diseqc_repeats = x
1243
1244         x = ConfigInteger(default=50, limits = (0, 9999))
1245         x.save_forced = False
1246         x.addNotifier(lambda configElement: secClass.setParam(secClass.DELAY_AFTER_LAST_DISEQC_CMD, configElement.value))
1247         config.sec.delay_after_last_diseqc_command = x
1248
1249         x = ConfigInteger(default=50, limits = (0, 9999))
1250         x.save_forced = False
1251         x.addNotifier(lambda configElement: secClass.setParam(secClass.DELAY_AFTER_TONEBURST, configElement.value))
1252         config.sec.delay_after_toneburst = x
1253
1254         x = ConfigInteger(default=20, limits = (0, 9999))
1255         x.save_forced = False
1256         x.addNotifier(lambda configElement: secClass.setParam(secClass.DELAY_AFTER_VOLTAGE_CHANGE_BEFORE_SWITCH_CMDS, configElement.value))
1257         config.sec.delay_after_change_voltage_before_switch_command = x
1258
1259         x = ConfigInteger(default=1000, limits = (0, 9999))
1260         x.save_forced = False
1261         x.addNotifier(lambda configElement: secClass.setParam(secClass.DELAY_AFTER_ENABLE_VOLTAGE_BEFORE_SWITCH_CMDS, configElement.value))
1262         config.sec.delay_after_enable_voltage_before_switch_command = x
1263
1264         x = ConfigInteger(default=500, limits = (0, 9999))
1265         x.save_forced = False
1266         x.addNotifier(lambda configElement: secClass.setParam(secClass.DELAY_AFTER_VOLTAGE_CHANGE_BEFORE_MEASURE_IDLE_INPUTPOWER, configElement.value))
1267         config.sec.delay_after_voltage_change_before_measure_idle_inputpower = x
1268
1269         x = ConfigInteger(default=900, limits = (0, 9999))
1270         x.save_forced = False
1271         x.addNotifier(lambda configElement: secClass.setParam(secClass.DELAY_AFTER_ENABLE_VOLTAGE_BEFORE_MOTOR_CMD, configElement.value))
1272         config.sec.delay_after_enable_voltage_before_motor_command = x
1273
1274         x = ConfigInteger(default=500, limits = (0, 9999))
1275         x.save_forced = False
1276         x.addNotifier(lambda configElement: secClass.setParam(secClass.DELAY_AFTER_MOTOR_STOP_CMD, configElement.value))
1277         config.sec.delay_after_motor_stop_command = x
1278
1279         x = ConfigInteger(default=500, limits = (0, 9999))
1280         x.save_forced = False
1281         x.addNotifier(lambda configElement: secClass.setParam(secClass.DELAY_AFTER_VOLTAGE_CHANGE_BEFORE_MOTOR_CMD, configElement.value))
1282         config.sec.delay_after_voltage_change_before_motor_command = x
1283
1284         x = ConfigInteger(default=70, limits = (0, 9999))
1285         x.save_forced = False
1286         x.addNotifier(lambda configElement: secClass.setParam(secClass.DELAY_BEFORE_SEQUENCE_REPEAT, configElement.value))
1287         config.sec.delay_before_sequence_repeat = x
1288
1289         x = ConfigInteger(default=360, limits = (0, 9999))
1290         x.save_forced = False
1291         x.addNotifier(lambda configElement: secClass.setParam(secClass.MOTOR_RUNNING_TIMEOUT, configElement.value))
1292         config.sec.motor_running_timeout = x
1293
1294         x = ConfigInteger(default=1, limits = (0, 5))
1295         x.save_forced = False
1296         x.addNotifier(lambda configElement: secClass.setParam(secClass.MOTOR_COMMAND_RETRIES, configElement.value))
1297         config.sec.motor_command_retries = x
1298
1299         x = ConfigInteger(default=50, limits = (0, 9999))
1300         x.save_forced = False
1301         x.addNotifier(lambda configElement: secClass.setParam(secClass.DELAY_AFTER_DISEQC_RESET_CMD, configElement.value))
1302         config.sec.delay_after_diseqc_reset_cmd = x
1303
1304         x = ConfigInteger(default=150, limits = (0, 9999))
1305         x.save_forced = False
1306         x.addNotifier(lambda configElement: secClass.setParam(secClass.DELAY_AFTER_DISEQC_PERIPHERIAL_POWERON_CMD, configElement.value))
1307         config.sec.delay_after_diseqc_peripherial_poweron_cmd = x
1308
1309         x = ConfigInteger(default=10, limits = (0, 9999))
1310         x.save_forced = False
1311         x.addNotifier(lambda configElement: secClass.setParam(secClass.DELAY_AFTER_VOLTAGE_CHANGE_BEFORE_UNICABLE_CMD, configElement.value))
1312         config.sec.delay_after_voltage_change_before_unicable_cmd = x
1313
1314         x = ConfigInteger(default=5, limits = (0, 9999))
1315         x.save_forced = False
1316         x.addNotifier(lambda configElement: secClass.setParam(secClass.DELAY_AFTER_UNICABLE_CMD, configElement.value))
1317         config.sec.delay_after_unicable_cmd = x
1318
1319         x = ConfigInteger(default=10, limits = (0, 9999))
1320         x.save_forced = False
1321         x.addNotifier(lambda configElement: secClass.setParam(secClass.DELAY_AFTER_UNICABLE_FINAL_VOLTAGE_CHANGE, configElement.value))
1322         config.sec.delay_after_unicable_final_voltage_change = x
1323
1324 # TODO add support for satpos depending nims to advanced nim configuration
1325 # so a second/third/fourth cable from a motorized lnb can used behind a
1326 # diseqc 1.0 / diseqc 1.1 / toneburst switch
1327 # the C(++) part should can handle this
1328 # the configElement should be only visible when diseqc 1.2 is disabled
1329
1330
1331 def getMaxScr(format):
1332         return 32 if format == "EN50607" else 8
1333
1334 def getDefaultScr(format):
1335         if format == "EN50607":
1336                 return (
1337                         (984, (950, 2150)),
1338                         (1020, (950, 2150)),
1339                         (1056, (950, 2150)),
1340                         (1092, (950, 2150)),
1341                         (1128, (950, 2150)),
1342                         (1164, (950, 2150)),
1343                         (1210, (950, 2150)),
1344                         (1256, (950, 2150)),
1345                         (1292, (950, 2150)),
1346                         (1328, (950, 2150)),
1347                         (1364, (950, 2150)),
1348                         (1420, (950, 2150)),
1349                         (1458, (950, 2150)),
1350                         (1494, (950, 2150)),
1351                         (1530, (950, 2150)),
1352                         (1566, (950, 2150)),
1353                         (1602, (950, 2150)),
1354                         (1638, (950, 2150)),
1355                         (1680, (950, 2150)),
1356                         (1716, (950, 2150)),
1357                         (1752, (950, 2150)),
1358                         (1788, (950, 2150)),
1359                         (1824, (950, 2150)),
1360                         (1860, (950, 2150)),
1361                         (1896, (950, 2150)),
1362                         (1932, (950, 2150)),
1363                         (2004, (950, 2150)),
1364                         (2040, (950, 2150)),
1365                         (2076, (950, 2150)),
1366                         (2112, (950, 2150)),
1367                         (2148, (950, 2150)),
1368                         (2096, (950, 2150)),
1369                 )
1370         else:
1371                 return (
1372                         (1284, (950, 2150)),
1373                         (1400, (950, 2150)),
1374                         (1516, (950, 2150)),
1375                         (1632, (950, 2150)),
1376                         (1748, (950, 2150)),
1377                         (1864, (950, 2150)),
1378                         (1980, (950, 2150)),
1379                         (2096, (950, 2150)),
1380                 )
1381
1382 class UnicableProducts(object):
1383         def __init__(self):
1384                 self._lnbs = {}
1385                 self._matrices = {}
1386                 self._lnbManufacturers = []
1387                 self._matrixManufacturers = []
1388
1389         def parseLnbs(self, xmlRoot):
1390                 self._parseUnicableProducts(xmlRoot, self._lnbs)
1391                 self._lnbManufacturers = self._lnbs.keys()
1392                 self._lnbManufacturers.sort()
1393
1394         def getLnbs(self):
1395                 return self._lnbs
1396         lnbs = property(getLnbs)
1397
1398         def getLnbManufacturers(self):
1399                 return self._lnbManufacturers
1400         lnbManufacturers = property(getLnbManufacturers)
1401
1402         def getManufacturerLnbs(self, manufacturer):
1403                 return self._lnbs.get(manufacturer, [])
1404
1405         def parseMatrices(self, xmlRoot):
1406                 self._parseUnicableProducts(xmlRoot, self._matrices)
1407                 self._matrixManufacturers = self._matrices.keys()
1408                 self._matrixManufacturers.sort()
1409
1410         def getMatrices(self):
1411                 return self._matrices
1412         matrices = property(getMatrices)
1413
1414         def getMatrixManufacturers(self):
1415                 return self._matrixManufacturers
1416         matrixManufacturers = property(getMatrixManufacturers)
1417
1418         def getManufacturerMatrices(self, manufacturer):
1419                 return self._matrices.get(manufacturer, [])
1420
1421         def createProductsConfig(self, products, vco_null_check, configElement=None, create_scrs=False):
1422                 if products:
1423                         productKeys = products.keys()
1424                         productKeys.sort()
1425
1426                 if configElement is None:
1427                         configElement = ConfigSubsection()
1428                         configElement.product = ConfigText() if products is None else ConfigSelection(choices = productKeys, default = productKeys[0])
1429                         configElement.mode = ConfigInteger(default=0)
1430                         configElement.vco = ConfigSubList()
1431                         configElement.positions = ConfigSubList()
1432                         configElement.lofl = ConfigSubList()
1433                         configElement.lofh = ConfigSubList()
1434                         configElement.loft = ConfigSubList()
1435                         if products is None:
1436                                 return configElement
1437                 else:
1438                         def resetConfigSubList(sublist):
1439                                 del sublist[:]
1440                                 sublist.stored_values = {}
1441                                 sublist.index = 0
1442
1443                         if isinstance(configElement.product, ConfigText) or configElement.product.value not in productKeys:
1444                                 configElement.product = ConfigSelection(choices = productKeys, default = productKeys[0])
1445                         resetConfigSubList(configElement.vco)
1446                         resetConfigSubList(configElement.positions)
1447                         resetConfigSubList(configElement.lofl)
1448                         resetConfigSubList(configElement.lofh)
1449                         resetConfigSubList(configElement.loft)
1450
1451                 scrlist = []
1452                 vcolist = products[configElement.product.value]
1453                 lof_tuple = vcolist[len(vcolist)-1]
1454
1455                 configElement.mode.value = 1 if lof_tuple[4] == "EN50607" else 0
1456
1457                 for cnt in range(1,1+len(vcolist)-1):
1458                         vcofreq = int(vcolist[cnt-1])
1459                         if vcofreq == 0 and vco_null_check:
1460                                 scrlist.append(("%d" %cnt,"SCR %d " %cnt +_("not used")))
1461                         else:
1462                                 scrlist.append(("%d" %cnt,"SCR %d" %cnt))
1463                         configElement.vco.append(NoSave(ConfigInteger(default=vcofreq, limits = (vcofreq, vcofreq))))
1464
1465                 # we override cancel here because the original cancel does not set the old
1466                 # value when value is not in choices.. in this case self.default is set
1467                 # so we temporaray override self.default here for the scr config element
1468                 def cancel(self):
1469                         stored_default = self.default
1470                         self.default = self.saved_value
1471                         ConfigSelection.cancel(self)
1472                         self.default = stored_default
1473
1474                 sv = configElement.scr.saved_value if hasattr(configElement, "scr") else None
1475                 save_forced = True if sv is None else configElement.scr.save_forced
1476                 configElement.scr = ConfigSelection(scrlist, default = scrlist[0][0])
1477                 configElement.scr.save_forced = save_forced
1478                 configElement.scr.cancel = boundFunction(cancel, configElement.scr)
1479                 if sv is not None:
1480                         configElement.scr.value = sv
1481                         configElement.scr.saved_value = sv
1482
1483                 if create_scrs:
1484                         sv = configElement.scrs.saved_value if hasattr(configElement, "scrs") else None
1485                         save_forced = True if sv is None else configElement.scrs.save_forced
1486                         scrs = None if sv is None else literal_eval(sv)
1487                         choices = [ int(x) for x in vcolist[:-1] ]
1488                         configElement.scrs = ConfigSet(default = [ int(vcolist[0]) ], choices = choices, resort = False)
1489                         configElement.scrs.save_forced = save_forced
1490                         if sv is not None:
1491                                 configElement.scrs.saved_value = sv
1492                         if scrs is not None and set(scrs).issubset(set(choices)):
1493                                 configElement.scrs.value = scrs
1494                         elif not set(configElement.scrs.value).issubset(set(choices)):
1495                                 configElement.scrs.value = configElement.scrs.default
1496                 else:
1497                         configElement.scrs = ConfigNothing()
1498
1499                 positions = int(lof_tuple[0])
1500                 configElement.positions.append(ConfigInteger(default=positions, limits = (positions, positions)))
1501
1502                 lofl = int(lof_tuple[1])
1503                 configElement.lofl.append(ConfigInteger(default=lofl, limits = (lofl, lofl)))
1504
1505                 lofh = int(lof_tuple[2])
1506                 configElement.lofh.append(ConfigInteger(default=lofh, limits = (lofh, lofh)))
1507
1508                 loft = int(lof_tuple[3])
1509                 configElement.loft.append(ConfigInteger(default=loft, limits = (loft, loft)))
1510
1511                 print "manufacturer", configElement.manufacturer.value, "product", configElement.product.value
1512
1513                 return configElement
1514
1515         def _parseUnicableProducts(self, xmlRoot, productDict):
1516                 for manufacturer in xmlRoot.getchildren():
1517                         m={}
1518                         for product in manufacturer.getchildren():
1519                                 scr=[]
1520                                 lscr = []
1521                                 format = product.get("format", "EN50494").upper()
1522                                 if format in ('JESS', 'UNICABLE2', 'SCD2', 'EN50607', 'EN 50607'):
1523                                         format = "EN50607"
1524                                 else:
1525                                         format = "EN50494"
1526                                 for i in range(1,getMaxScr(format) + 1):
1527                                         lscr.append("scr%s" %(i,))
1528                                 lscr = tuple(lscr)
1529                                 for i in range(len(lscr)):
1530                                         myscr = product.get(lscr[i],"0")
1531                                         if(myscr != "0"):
1532                                                 scr.append(myscr)
1533                                 lof=[]
1534                                 lof.append(int(product.get("positions",1)))
1535                                 lof.append(int(product.get("lofl",9750)))
1536                                 lof.append(int(product.get("lofh",10600)))
1537                                 lof.append(int(product.get("threshold",11700)))
1538                                 lof.append(format)
1539                                 scr.append(tuple(lof))
1540                                 m.update({product.get("name"):tuple(scr)})
1541                         productDict.update({manufacturer.get("name"):m})
1542
1543 unicableProducts = UnicableProducts()
1544
1545 def configLOFChanged(configElement):
1546         global nimmanager
1547         nimmgr = nimmanager
1548         if configElement.value == "unicable":
1549                 x = configElement.slot_id
1550                 lnb = configElement.lnb_id
1551                 nim = config.Nims[x]
1552                 lnbs = nim.advanced.lnb
1553                 section = lnbs[lnb]
1554                 create_scrs = nimmgr.nim_slots[x].inputs is not None
1555
1556                 if isinstance(section.unicable, ConfigNothing):
1557                         unicable_choices = {
1558                                 "unicable_lnb": _("Unicable LNB"),
1559                                 "unicable_matrix": _("Unicable Matrix"),
1560                                 "unicable_user": "Unicable "+_("User defined")}
1561                         unicable_choices_default = "unicable_lnb"
1562                         section.unicable = ConfigSelection(unicable_choices, unicable_choices_default)
1563                         section.unicable.slot_id = x
1564                         section.unicable.lnb_id = lnb
1565                         section.unicable_use_pin = ConfigYesNo(default = False)
1566                         section.unicable_pin = ConfigInteger(default=0, limits=(0, 255))
1567
1568                 if section.unicable.value == "unicable_matrix":
1569                         print "MATRIX"
1570                         matrixConfig = section.unicableMatrix if hasattr(section, "unicableMatrix") else None
1571                         manufacturer = unicableProducts.getMatrixManufacturers()[0]
1572
1573                         if matrixConfig:
1574                                 manufacturer = matrixConfig.manufacturer.value
1575                         else:
1576                                 matrixConfig = unicableProducts.createProductsConfig(None, True, matrixConfig)
1577                                 section.unicableMatrix = matrixConfig
1578                                 matrixConfig.manufacturer = ConfigSelection(unicableProducts.getMatrixManufacturers(), default=manufacturer)
1579                                 manufacturer = matrixConfig.manufacturer.value
1580
1581                         unicableMatrix = unicableProducts.createProductsConfig(unicableProducts.getManufacturerMatrices(manufacturer), True, matrixConfig, create_scrs)
1582
1583                         if not matrixConfig:
1584                                 section.unicableMatrix = unicableMatrix
1585                                 if not hasattr(section.unicableMatrix, "manufacturer"):
1586                                         section.unicableMatrix.manufacturer = ConfigSelection(unicableProducts.getMatrixManufacturers(), default=manufacturer)
1587
1588                 elif section.unicable.value == "unicable_lnb":
1589                         print "LNB"
1590                         lnbConfig = section.unicableLnb if hasattr(section, "unicableLnb") else None
1591                         manufacturer = unicableProducts.getLnbManufacturers()[0]
1592
1593                         if lnbConfig:
1594                                 manufacturer = lnbConfig.manufacturer.value
1595                         else:
1596                                 lnbConfig = unicableProducts.createProductsConfig(None, True, lnbConfig)
1597                                 section.unicableLnb = lnbConfig
1598                                 lnbConfig.manufacturer = ConfigSelection(unicableProducts.getLnbManufacturers(), default=manufacturer)
1599                                 manufacturer = lnbConfig.manufacturer.value
1600
1601                         unicableLnb = unicableProducts.createProductsConfig(unicableProducts.getManufacturerLnbs(manufacturer), False, lnbConfig, create_scrs)
1602
1603                         if not lnbConfig:
1604                                 section.unicableLnb = unicableLnb
1605                                 if not hasattr(section.unicableLnb, "manufacturer"):
1606                                         section.unicableLnb.manufacturer = ConfigSelection(unicableProducts.getLnbManufacturers(), default=manufacturer)
1607
1608                 elif section.unicable.value == "unicable_user":
1609                         print "USER"
1610                         advanced_lnb_satcruser_choices = []
1611                         for i in range(1, getMaxScr("EN50607") + 1):
1612                                 advanced_lnb_satcruser_choices.append((str(i), "SatCR %s" %(i,)))
1613
1614                         if not hasattr(section, "satcruser"):
1615                                 mode_choices = [ ("EN50494", _("Unicable 1")), ("EN50607", _("Unicable 2 / JESS")) ]
1616                                 section.satcruser_mode = ConfigSelection(mode_choices, default="EN50494")
1617                                 section.satcruser = ConfigSelection(advanced_lnb_satcruser_choices, default="1")
1618                                 tmp = ConfigSubList()
1619                                 for entry in getDefaultScr("EN50607"):
1620                                         tmp.append(ConfigInteger(default=entry[0], limits=entry[1])) #TODO properly pass format
1621                                 section.satcrvcouser = tmp
1622
1623                 if not hasattr(nim.advanced, "unicableconnected"):
1624                         nim.advanced.unicableconnected = ConfigYesNo(default=False)
1625                         nim.advanced.unicableconnectedTo = ConfigSelection([(str(id), nimmgr.getNimDescription(id)) for id in nimmgr.getNimListOfType("DVB-S") if id != x])
1626
1627 def InitNimManager(nimmgr, slot_no = None):
1628         global unicableProducts
1629         hw = HardwareInfo()
1630         addNimConfig = False
1631         try:
1632                 config.Nims
1633                 assert slot_no is not None, "FATAL: you must call InitNimManager(nimmgr, slot_no = X) to reinitialize SINGLE nim slots"
1634         except:
1635                 addNimConfig = True
1636
1637         if addNimConfig:
1638                 InitSecParams()
1639                 config.Nims = ConfigSubList()
1640                 for x in range(len(nimmgr.nim_slots)):
1641                         config.Nims.append(ConfigSubsection())
1642
1643         lnb_choices = {
1644                 "universal_lnb": _("Universal LNB"),
1645                 "unicable": _("Unicable"),
1646                 "c_band": _("C-Band"),
1647                 "user_defined": _("User defined")}
1648
1649         lnb_choices_default = "universal_lnb"
1650
1651         try:
1652                 doc = xml.etree.cElementTree.parse(eEnv.resolve("${sysconfdir}/enigma2/unicable.xml"))
1653         except IOError:
1654                 doc = xml.etree.cElementTree.parse(eEnv.resolve("${datadir}/enigma2/unicable.xml"))
1655         root = doc.getroot()
1656
1657         entry = root.find("lnb")
1658         unicableProducts.parseLnbs(entry)
1659         entry = root.find("matrix")
1660         unicableProducts.parseMatrices(entry)
1661
1662         prio_list = [ ("-1", _("Auto")) ]
1663         prio_list += [(str(prio), str(prio)) for prio in range(65)+range(14000,14065)+range(19000,19065)]
1664
1665         advanced_lnb_csw_choices = [("none", _("None")), ("AA", _("AA")), ("AB", _("AB")), ("BA", _("BA")), ("BB", _("BB"))]
1666         advanced_lnb_csw_choices += [(str(0xF0|y), "Input " + str(y+1)) for y in range(0, 16)]
1667
1668         advanced_lnb_ucsw_choices = [("0", _("None"))] + [(str(y), "Input " + str(y)) for y in range(1, 17)]
1669
1670         diseqc_mode_choices = [
1671                 ("single", _("Single")), ("toneburst_a_b", _("Toneburst A/B")),
1672                 ("diseqc_a_b", _("DiSEqC A/B")), ("diseqc_a_b_c_d", _("DiSEqC A/B/C/D")),
1673                 ("positioner", _("Positioner"))]
1674
1675         positioner_mode_choices = [("usals", _("USALS")), ("manual", _("manual"))]
1676
1677         diseqc_satlist_choices = [(3601, _('nothing connected'), 1)] + nimmgr.satList
1678
1679         longitude_orientation_choices = [("east", _("East")), ("west", _("West"))]
1680         latitude_orientation_choices = [("north", _("North")), ("south", _("South"))]
1681         turning_speed_choices = [("fast", _("Fast")), ("slow", _("Slow")), ("fast epoch", _("Fast epoch"))]
1682
1683         advanced_satlist_choices = nimmgr.satList + [
1684                 (3601, _('All Satellites')+' 1', 1), (3602, _('All Satellites')+' 2', 1),
1685                 (3603, _('All Satellites')+' 3', 1), (3604, _('All Satellites')+' 4', 1)]
1686         advanced_lnb_choices = [("0", "not available")] + [(str(y), "LNB " + str(y)) for y in range(1, 33)]
1687         advanced_voltage_choices = [("polarization", _("Polarization")), ("13V", _("13 V")), ("18V", _("18 V"))]
1688         advanced_tonemode_choices = [("band", _("Band")), ("on", _("On")), ("off", _("Off"))]
1689         advanced_lnb_toneburst_choices = [("none", _("None")), ("A", _("A")), ("B", _("B"))]
1690         advanced_lnb_allsat_diseqcmode_choices = [("1_2", _("1.2"))]
1691         advanced_lnb_diseqcmode_choices = [("none", _("None")), ("1_0", _("1.0")), ("1_1", _("1.1")), ("1_2", _("1.2"))]
1692         advanced_lnb_commandOrder1_0_choices = [("ct", "committed, toneburst"), ("tc", "toneburst, committed")]
1693         advanced_lnb_commandOrder_choices = [
1694                 ("ct", "committed, toneburst"), ("tc", "toneburst, committed"),
1695                 ("cut", "committed, uncommitted, toneburst"), ("tcu", "toneburst, committed, uncommitted"),
1696                 ("uct", "uncommitted, committed, toneburst"), ("tuc", "toneburst, uncommitted, commmitted")]
1697         advanced_lnb_diseqc_repeat_choices = [("none", _("None")), ("one", _("One")), ("two", _("Two")), ("three", _("Three"))]
1698         advanced_lnb_fast_turning_btime = mktime(datetime(1970, 1, 1, 7, 0).timetuple());
1699         advanced_lnb_fast_turning_etime = mktime(datetime(1970, 1, 1, 19, 0).timetuple());
1700
1701         def configDiSEqCModeChanged(configElement):
1702                 section = configElement.section
1703                 if configElement.value == "1_2" and isinstance(section.longitude, ConfigNothing):
1704                         section.longitude = ConfigFloat(default = [5,100], limits = [(0,359),(0,999)])
1705                         section.longitudeOrientation = ConfigSelection(longitude_orientation_choices, "east")
1706                         section.latitude = ConfigFloat(default = [50,767], limits = [(0,359),(0,999)])
1707                         section.latitudeOrientation = ConfigSelection(latitude_orientation_choices, "north")
1708                         section.powerMeasurement = ConfigYesNo(default=True)
1709                         section.powerThreshold = ConfigInteger(default=15, limits=(0, 100))
1710                         section.turningSpeed = ConfigSelection(turning_speed_choices, "fast")
1711                         section.degreePerSecond = ConfigFloat(default = [0,5], limits=[(0,360),(0,9)])
1712                         section.fastTurningBegin = ConfigDateTime(default=advanced_lnb_fast_turning_btime, formatstring = _("%H:%M"), increment = 600)
1713                         section.fastTurningEnd = ConfigDateTime(default=advanced_lnb_fast_turning_etime, formatstring = _("%H:%M"), increment = 600)
1714
1715         def configLNBChanged(configElement):
1716                 x = configElement.slot_id
1717                 nim = config.Nims[x]
1718                 if isinstance(configElement.value, tuple):
1719                         lnb = int(configElement.value[0])
1720                 else:
1721                         lnb = int(configElement.value)
1722                 lnbs = nim.advanced.lnb
1723                 if lnb and lnb not in lnbs:
1724                         section = lnbs[lnb] = ConfigSubsection()
1725                         section.lofl = ConfigInteger(default=9750, limits = (0, 99999))
1726                         section.lofh = ConfigInteger(default=10600, limits = (0, 99999))
1727                         section.threshold = ConfigInteger(default=11700, limits = (0, 99999))
1728 #                       section.output_12v = ConfigSelection(choices = [("0V", _("0 V")), ("12V", _("12 V"))], default="0V")
1729                         section.increased_voltage = ConfigYesNo(False)
1730                         section.toneburst = ConfigSelection(advanced_lnb_toneburst_choices, "none")
1731                         section.longitude = ConfigNothing()
1732                         if lnb > 32:
1733                                 tmp = ConfigSelection(advanced_lnb_allsat_diseqcmode_choices, "1_2")
1734                                 tmp.section = section
1735                                 configDiSEqCModeChanged(tmp)
1736                         else:
1737                                 tmp = ConfigSelection(advanced_lnb_diseqcmode_choices, "none")
1738                                 tmp.section = section
1739                                 tmp.addNotifier(configDiSEqCModeChanged)
1740                         section.diseqcMode = tmp
1741                         section.commitedDiseqcCommand = ConfigSelection(advanced_lnb_csw_choices)
1742                         section.fastDiseqc = ConfigYesNo(False)
1743                         section.sequenceRepeat = ConfigYesNo(False)
1744                         section.commandOrder1_0 = ConfigSelection(advanced_lnb_commandOrder1_0_choices, "ct")
1745                         section.commandOrder = ConfigSelection(advanced_lnb_commandOrder_choices, "ct")
1746                         section.uncommittedDiseqcCommand = ConfigSelection(advanced_lnb_ucsw_choices)
1747                         section.diseqcRepeats = ConfigSelection(advanced_lnb_diseqc_repeat_choices, "none")
1748                         section.prio = ConfigSelection(prio_list, "-1")
1749                         section.unicable = ConfigNothing()
1750                         tmp = ConfigSelection(lnb_choices, lnb_choices_default)
1751                         tmp.slot_id = x
1752                         tmp.lnb_id = lnb
1753                         tmp.addNotifier(configLOFChanged, initial_call = False)
1754                         section.lof = tmp
1755
1756         def configModeChanged(configMode):
1757                 slot_id = configMode.slot_id
1758                 nim = config.Nims[slot_id]
1759                 if configMode.value == "advanced" and isinstance(nim.advanced, ConfigNothing):
1760                         # advanced config:
1761                         nim.advanced = ConfigSubsection()
1762                         nim.advanced.sat = ConfigSubDict()
1763                         nim.advanced.sats = getConfigSatlist(192, advanced_satlist_choices)
1764                         nim.advanced.lnb = ConfigSubDict()
1765                         nim.advanced.lnb[0] = ConfigNothing()
1766                         for x in nimmgr.satList:
1767                                 tmp = ConfigSubsection()
1768                                 tmp.voltage = ConfigSelection(advanced_voltage_choices, "polarization")
1769                                 tmp.tonemode = ConfigSelection(advanced_tonemode_choices, "band")
1770                                 tmp.usals = ConfigYesNo(True)
1771                                 tmp.rotorposition = ConfigInteger(default=1, limits=(1, 255))
1772                                 lnb = ConfigSelection(advanced_lnb_choices, "0")
1773                                 lnb.slot_id = slot_id
1774                                 lnb.addNotifier(configLNBChanged, initial_call = False)
1775                                 lnb.save_forced = False
1776                                 tmp.lnb = lnb
1777                                 nim.advanced.sat[x[0]] = tmp
1778                         for x in range(3601, 3605):
1779                                 tmp = ConfigSubsection()
1780                                 tmp.voltage = ConfigSelection(advanced_voltage_choices, "polarization")
1781                                 tmp.tonemode = ConfigSelection(advanced_tonemode_choices, "band")
1782                                 tmp.usals = ConfigYesNo(default=True)
1783                                 tmp.rotorposition = ConfigInteger(default=1, limits=(1, 255))
1784                                 lnbnum = 33+x-3601
1785                                 lnb = ConfigSelection([("0", "not available"), (str(lnbnum), "LNB %d"%(lnbnum))], "0")
1786                                 lnb.slot_id = slot_id
1787                                 lnb.addNotifier(configLNBChanged, initial_call = False)
1788                                 lnb.save_forced = False
1789                                 tmp.lnb = lnb
1790                                 nim.advanced.sat[x] = tmp
1791
1792         def scpcSearchRangeChanged(configElement):
1793                 fe_id = configElement.fe_id
1794                 with open("/proc/stb/frontend/%d/use_scpc_optimized_search_range" %(fe_id), "w") as f:
1795                         f.write(configElement.value)
1796
1797         def toneAmplitudeChanged(configElement):
1798                 fe_id = configElement.fe_id
1799                 slot_id = configElement.slot_id
1800                 if nimmgr.nim_slots[slot_id].description == 'Alps BSBE2':
1801                         with open("/proc/stb/frontend/%d/tone_amplitude" %(fe_id), "w") as f:
1802                                 f.write(configElement.value)
1803
1804         def connectedToChanged(slot_id, nimmgr, configElement):
1805                 configMode = nimmgr.getNimConfig(slot_id).sat.configMode
1806                 if configMode.value == 'loopthrough':
1807                         internally_connectable = nimmgr.nimInternallyConnectableTo(slot_id)
1808                         dest_slot = configElement.value
1809                         if internally_connectable is not None and int(internally_connectable) == int(dest_slot):
1810                                 configMode.choices.updateItemDescription(configMode.index, _("internally loopthrough to"))
1811                         else:
1812                                 configMode.choices.updateItemDescription(configMode.index, _("externally loopthrough to"))
1813
1814         for slot in nimmgr.nim_slots:
1815                 x = slot.slot
1816
1817                 # only re-init specific nim slot when InitNimManager is called again
1818                 if slot_no is not None and x != slot_no:
1819                         continue
1820
1821                 nim = config.Nims[x]
1822                 addMultiType = False
1823                 try:
1824                         nim.multiType
1825                 except:
1826                         addMultiType = True
1827                 if addMultiType:
1828                         typeList = []
1829                         for key, value in slot.types.iteritems():
1830                                 typeList.append((key, value))
1831                         nim.multiType = ConfigSelection(typeList, "0")
1832                         nim.multiType.enabled = len(typeList) > 1
1833                         nim.multiType.slot_id = x
1834
1835         getConfigModeTuple=nimmgr.getConfigModeTuple
1836
1837         empty_slots = 0
1838         for slot in nimmgr.nim_slots:
1839                 x = slot.slot
1840
1841                 # only re-init specific nim slot when InitNimManager is called again
1842                 if slot_no is not None and x != slot_no:
1843                         continue
1844
1845                 nim = config.Nims[x]
1846                 isEmpty = True
1847
1848                 nim.configMode = ConfigSelection(choices={
1849                         "nothing" : NimManager.config_mode_str["nothing"],
1850                         "multi" : NimManager.config_mode_str["multi"],
1851                         "enabled" : NimManager.config_mode_str["enabled"],
1852                         "simple" : NimManager.config_mode_str["simple"],
1853                         "advanced" : NimManager.config_mode_str["advanced"],
1854                         "equal" : NimManager.config_mode_str["equal"],
1855                         "satposdepends" : NimManager.config_mode_str["satposdepends"],
1856                         "loopthrough" : "", # description is dynamically generated by connectedToChanged function (InitNimManager)
1857                 }, default = "multi")
1858
1859                 if slot.isCompatible("DVB-S"):
1860                         isEmpty = False
1861                         nim.toneAmplitude = ConfigSelection([("11", "340mV"), ("10", "360mV"), ("9", "600mV"), ("8", "700mV"), ("7", "800mV"), ("6", "900mV"), ("5", "1100mV")], "7")
1862                         nim.toneAmplitude.fe_id = x - empty_slots
1863                         nim.toneAmplitude.slot_id = x
1864                         nim.toneAmplitude.addNotifier(toneAmplitudeChanged)
1865                         nim.scpcSearchRange = ConfigSelection([("0", _("no")), ("1", _("yes"))], "0")
1866                         nim.scpcSearchRange.slot_id = x
1867                         fe_id =  x - empty_slots
1868                         if exists('/proc/stb/frontend/%d/use_scpc_optimized_search_range' % fe_id):
1869                                 nim.scpcSearchRange.fe_id = fe_id
1870                                 nim.scpcSearchRange.addNotifier(scpcSearchRangeChanged)
1871                         else:
1872                                 nim.scpcSearchRange.fe_id = None
1873                         nim.diseqc13V = ConfigYesNo(False)
1874                         nim.diseqcMode = ConfigSelection(diseqc_mode_choices, "diseqc_a_b")
1875                         nim.connectedTo = ConfigSelection([(str(id), nimmgr.getNimDescription(id)) for id in nimmgr.getNimListOfType("DVB-S") if id != x])
1876                         nim.simpleSingleSendDiSEqC = ConfigYesNo(False)
1877                         nim.simpleDiSEqCSetVoltageTone = ConfigYesNo(True)
1878                         nim.simpleDiSEqCOnlyOnSatChange = ConfigYesNo(False)
1879                         nim.diseqcA = getConfigSatlist(192, diseqc_satlist_choices)
1880                         nim.diseqcB = getConfigSatlist(130, diseqc_satlist_choices)
1881                         nim.diseqcC = ConfigSatlist(list = diseqc_satlist_choices)
1882                         nim.diseqcD = ConfigSatlist(list = diseqc_satlist_choices)
1883                         nim.positionerMode = ConfigSelection(positioner_mode_choices, "usals")
1884                         nim.longitude = ConfigFloat(default=[5,100], limits=[(0,359),(0,999)])
1885                         nim.longitudeOrientation = ConfigSelection(longitude_orientation_choices, "east")
1886                         nim.latitude = ConfigFloat(default=[50,767], limits=[(0,359),(0,999)])
1887                         nim.latitudeOrientation = ConfigSelection(latitude_orientation_choices, "north")
1888                         nim.positionerExclusively = ConfigYesNo(True)
1889                         nim.powerMeasurement = ConfigYesNo(True)
1890                         nim.powerThreshold = ConfigInteger(default=hw.get_device_name() == "dm8000" and 15 or 50, limits=(0, 100))
1891                         nim.turningSpeed = ConfigSelection(turning_speed_choices, "fast")
1892                         nim.degreePerSecond = ConfigFloat(default = [0,5], limits=[(0,360),(0,9)])
1893                         btime = datetime(1970, 1, 1, 7, 0);
1894                         nim.fastTurningBegin = ConfigDateTime(default = mktime(btime.timetuple()), formatstring = _("%H:%M"), increment = 900)
1895                         etime = datetime(1970, 1, 1, 19, 0);
1896                         nim.fastTurningEnd = ConfigDateTime(default = mktime(etime.timetuple()), formatstring = _("%H:%M"), increment = 900)
1897                         config_mode_choices = [ getConfigModeTuple("nothing"), getConfigModeTuple("simple"), getConfigModeTuple("advanced") ]
1898                         # FIXMEE
1899                         # no support for satpos depends, equal to and loopthough setting for nims with
1900                         # with multiple inputs and multiple channels
1901                         if slot.inputs is None:
1902                                 for val in slot.types.itervalues():
1903                                         if len(nimmgr.getNimListOfType(val, exception = x)) > 0:
1904                                                 config_mode_choices.append(getConfigModeTuple("equal"))
1905                                                 config_mode_choices.append(getConfigModeTuple("satposdepends"))
1906                                 if len(nimmgr.canConnectTo(x)) > 0:
1907                                         config_mode_choices.append(getConfigModeTuple("loopthrough"))
1908                         nim.advanced = ConfigNothing()
1909                         nim.sat = ConfigSubsection()
1910                         nim.sat.configMode = ConfigSelection(config_mode_choices, "nothing")
1911                         nim.sat.configMode.slot_id = x
1912                         nim.sat.configMode.connectedToChanged = boundFunction(connectedToChanged, x, nimmgr)
1913                         #Migrate old settings if existing
1914                         if nim.configMode.value != "multi":
1915                                 if not slot.isMultiType() or slot.types[nim.multiType.value].startswith("DVB-S"):
1916                                         Log.w("Migrating old DVB-S settings!")
1917                                         nim.sat.configMode.value = nim.configMode.value
1918                         nim.sat.configMode.addNotifier(configModeChanged, initial_call = True)
1919                         nim.connectedTo.addNotifier(boundFunction(connectedToChanged, x, nimmgr), initial_call = True)
1920                 if slot.isCompatible("DVB-C"):
1921                         isEmpty = False
1922                         nim.cable = ConfigSubsection()
1923                         nim.cable.configMode = ConfigSelection(
1924                                 choices = [ getConfigModeTuple("enabled"), getConfigModeTuple("nothing") ],
1925                                 default = "enabled" if not slot.isMultiType() or slot.types[nim.multiType.value] == "DVB-C" else "nothing")
1926                         list = [ ]
1927                         n = 0
1928                         for x in nimmgr.cablesList:
1929                                 list.append((str(n), x[0]))
1930                                 n += 1
1931                         possible_scan_types = [("bands", _("Frequency bands")), ("steps", _("Frequency steps"))]
1932                         if n:
1933                                 possible_scan_types.append(("provider", _("Provider")))
1934                                 nim.cable.scan_provider = ConfigSelection(default = "0", choices = list)
1935                         nim.cable.scan_type = ConfigSelection(default = "bands", choices = possible_scan_types)
1936                         nim.cable.scan_band_EU_VHF_I = ConfigYesNo(default = True)
1937                         nim.cable.scan_band_EU_MID = ConfigYesNo(default = True)
1938                         nim.cable.scan_band_EU_VHF_III = ConfigYesNo(default = True)
1939                         nim.cable.scan_band_EU_UHF_IV = ConfigYesNo(default = True)
1940                         nim.cable.scan_band_EU_UHF_V = ConfigYesNo(default = True)
1941                         nim.cable.scan_band_EU_SUPER = ConfigYesNo(default = True)
1942                         nim.cable.scan_band_EU_HYPER = ConfigYesNo(default = True)
1943                         nim.cable.scan_band_US_LOW = ConfigYesNo(default = False)
1944                         nim.cable.scan_band_US_MID = ConfigYesNo(default = False)
1945                         nim.cable.scan_band_US_HIGH = ConfigYesNo(default = False)
1946                         nim.cable.scan_band_US_SUPER = ConfigYesNo(default = False)
1947                         nim.cable.scan_band_US_HYPER = ConfigYesNo(default = False)
1948                         nim.cable.scan_band_US_ULTRA = ConfigYesNo(default = False)
1949                         nim.cable.scan_band_US_JUMBO = ConfigYesNo(default = False)
1950                         nim.cable.scan_frequency_steps = ConfigInteger(default = 1000, limits = (1000, 10000))
1951                         nim.cable.scan_mod_qam16 = ConfigYesNo(default = False)
1952                         nim.cable.scan_mod_qam32 = ConfigYesNo(default = False)
1953                         nim.cable.scan_mod_qam64 = ConfigYesNo(default = True)
1954                         nim.cable.scan_mod_qam128 = ConfigYesNo(default = False)
1955                         nim.cable.scan_mod_qam256 = ConfigYesNo(default = True)
1956                         nim.cable.scan_sr_6900 = ConfigYesNo(default = True)
1957                         nim.cable.scan_sr_6875 = ConfigYesNo(default = True)
1958                         nim.cable.scan_sr_ext1 = ConfigInteger(default = 0, limits = (0, 7230))
1959                         nim.cable.scan_sr_ext2 = ConfigInteger(default = 0, limits = (0, 7230))
1960                         #Migrate old settings if existing
1961                         if nim.configMode.value != "multi":
1962                                 if not slot.isMultiType() or slot.types[nim.multiType.value] == "DVB-C":
1963                                         Log.w("Migrating old DVB-C settings!")
1964                                         nim.cable.configMode.value = nim.configMode.value
1965                 if slot.isCompatible("DVB-T"):
1966                         isEmpty = False
1967                         nim.terrest = ConfigSubsection()
1968                         nim.terrest.configMode = ConfigSelection(
1969                                 choices = [ getConfigModeTuple("enabled"), getConfigModeTuple("nothing") ],
1970                                 default = "enabled" if not slot.isMultiType() or slot.types[nim.multiType.value].startswith("DVB-T") else "nothing")
1971                         provider = []
1972                         n = 0
1973                         for x in nimmgr.terrestrialsList:
1974                                 provider.append((str(n), x[0]))
1975                                 n += 1
1976                         nim.terrest.provider = ConfigSelection(choices = provider)
1977                         nim.terrest.use5V = ConfigOnOff()
1978                         #Migrate old settings
1979                         if nim.configMode.value != "multi":
1980                                 nim.terrestrial = NoSave(ConfigSelection(choices = provider, default="1"))
1981                                 nim.terrestrial_5V = NoSave(ConfigOnOff(default=False))
1982                                 if not slot.isMultiType() or slot.types[nim.multiType.value].startswith("DVB-T"):
1983                                         Log.w("Migrating old DVB-T settings!")
1984                                         nim.terrest.configMode.value = nim.configMode.value
1985                                 nim.terrest.provider.value = nim.terrestrial.value
1986                                 nim.terrest.use5V.value = nim.terrestrial_5V.value
1987
1988                 if isEmpty:
1989                         empty_slots += 1
1990                         nim.configMode = ConfigSelection(choices = { "nothing": _("disabled") }, default="nothing");
1991                 elif not slot.types:
1992                         print "pls add support for this frontend type!", slot.type
1993                 elif nim.configMode.value != "multi":
1994                         nim.configMode.value = "multi"
1995                         nim.save()
1996                         config.save()
1997
1998         nimmgr.sec = SecConfigure(nimmgr)
1999
2000 nimmanager = NimManager()
2001 InitNimManager(nimmanager)