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