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