add unicable support (thx to adenin)
[vuplus_dvbapp] / lib / python / Components / NimManager.py
1 from Tools.HardwareInfo import HardwareInfo
2
3 from config import config, ConfigSubsection, ConfigSelection, ConfigFloat, \
4         ConfigSatlist, ConfigYesNo, ConfigInteger, ConfigSubList, ConfigNothing, \
5         ConfigSubDict, ConfigOnOff, ConfigDateTime
6
7 from enigma import eDVBSatelliteEquipmentControl as secClass, \
8         eDVBSatelliteLNBParameters as lnbParam, \
9         eDVBSatelliteDiseqcParameters as diseqcParam, \
10         eDVBSatelliteSwitchParameters as switchParam, \
11         eDVBSatelliteRotorParameters as rotorParam, \
12         eDVBResourceManager, eDVBDB
13
14 from time import localtime, mktime
15 from datetime import datetime
16
17 from sets import Set
18
19 def getConfigSatlist(orbpos, satlist):
20         default_orbpos = None
21         for x in satlist:
22                 if x[0] == orbpos:
23                         default_orbpos = orbpos
24                         break
25         return ConfigSatlist(satlist, default_orbpos)
26
27 def tryOpen(filename):
28         try:
29                 procFile = open(filename)
30         except IOError:
31                 return None
32         return procFile
33
34 class SecConfigure:
35         def getConfiguredSats(self):
36                 return self.configuredSatellites
37
38         def addSatellite(self, sec, orbpos):
39                 sec.addSatellite(orbpos)
40                 self.configuredSatellites.add(orbpos)
41
42         def addLNBSimple(self, sec, slotid, 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):
43                 if orbpos is None or orbpos == 3601:
44                         return
45                 #simple defaults
46                 sec.addLNB()
47                 tunermask = 1 << slotid
48                 if self.equal.has_key(slotid):
49                         for slot in self.equal[slotid]:
50                                 tunermask |= (1 << slot)
51                 elif self.linked.has_key(slotid):
52                         for slot in self.linked[slotid]:
53                                 tunermask |= (1 << slot)
54                 sec.setLNBSatCR(-1)
55                 sec.setLNBNum(1)
56                 sec.setLNBLOFL(9750000)
57                 sec.setLNBLOFH(10600000)
58                 sec.setLNBThreshold(11700000)
59                 sec.setLNBIncreasedVoltage(lnbParam.OFF)
60                 sec.setRepeats(0)
61                 sec.setFastDiSEqC(fastDiSEqC)
62                 sec.setSeqRepeat(0)
63                 sec.setCommandOrder(0)
64
65                 #user values
66                 sec.setDiSEqCMode(diseqcmode)
67                 sec.setToneburst(toneburstmode)
68                 sec.setCommittedCommand(diseqcpos)
69                 sec.setUncommittedCommand(0) # SENDNO
70                 #print "set orbpos to:" + str(orbpos)
71
72                 if 0 <= diseqcmode < 3:
73                         self.addSatellite(sec, orbpos)
74                         if setVoltageTone:
75                                 if diseqc13V:
76                                         sec.setVoltageMode(switchParam.HV_13)
77                                 else:
78                                         sec.setVoltageMode(switchParam.HV)
79                                 sec.setToneMode(switchParam.HILO)
80                         else:
81                                 sec.setVoltageMode(switchParam._14V)
82                                 sec.setToneMode(switchParam.OFF)
83                 elif (diseqcmode == 3): # diseqc 1.2
84                         if self.satposdepends.has_key(slotid):
85                                 for slot in self.satposdepends[slotid]:
86                                         tunermask |= (1 << slot)
87                         sec.setLatitude(latitude)
88                         sec.setLaDirection(laDirection)
89                         sec.setLongitude(longitude)
90                         sec.setLoDirection(loDirection)
91                         sec.setUseInputpower(useInputPower)
92                         sec.setInputpowerDelta(inputPowerDelta)
93                         sec.setRotorTurningSpeed(turningSpeed)
94
95                         for x in self.NimManager.satList:
96                                 print "Add sat " + str(x[0])
97                                 self.addSatellite(sec, int(x[0]))
98                                 if diseqc13V:
99                                         sec.setVoltageMode(switchParam.HV_13)
100                                 else:
101                                         sec.setVoltageMode(switchParam.HV)
102                                 sec.setToneMode(switchParam.HILO)
103                                 sec.setRotorPosNum(0) # USALS
104                 
105                 sec.setLNBSlotMask(tunermask)
106
107         def setSatposDepends(self, sec, nim1, nim2):
108                 print "tuner", nim1, "depends on satpos of", nim2
109                 sec.setTunerDepends(nim1, nim2)
110
111         def linkNIMs(self, sec, nim1, nim2):
112                 print "link tuner", nim1, "to tuner", nim2
113                 sec.setTunerLinked(nim1, nim2)
114                 
115         def getRoot(self, slotid, connto):
116                 visited = []
117                 while (self.NimManager.getNimConfig(connto).configMode.value in ["satposdepends", "equal", "loopthrough"]):
118                         connto = int(self.NimManager.getNimConfig(connto).connectedTo.value)
119                         if connto in visited: # prevent endless loop
120                                 return slotid
121                         visited.append(connto)
122                 return connto
123
124         def update(self):
125                 sec = secClass.getInstance()
126                 self.configuredSatellites = Set()
127                 sec.clear() ## this do unlinking NIMs too !!
128                 print "sec config cleared"
129
130                 self.linked = { }
131                 self.satposdepends = { }
132                 self.equal = { }
133
134                 nim_slots = self.NimManager.nim_slots
135
136                 used_nim_slots = [ ]
137
138                 for slot in nim_slots:
139                         if slot.type is not None:
140                                 used_nim_slots.append((slot.slot, slot.description, slot.config.configMode.value != "nothing" and True or False, slot.isCompatible("DVB-S2")))
141                 eDVBResourceManager.getInstance().setFrontendSlotInformations(used_nim_slots)
142
143                 for slot in nim_slots:
144                         x = slot.slot
145                         nim = slot.config
146                         if slot.isCompatible("DVB-S"):
147                                 # save what nim we link to/are equal to/satposdepends to.
148                                 # this is stored in the *value* (not index!) of the config list
149                                 if nim.configMode.value == "equal":
150                                         connto = self.getRoot(x, int(nim.connectedTo.value))
151                                         if not self.equal.has_key(connto):
152                                                 self.equal[connto] = []
153                                         self.equal[connto].append(x)
154                                 elif nim.configMode.value == "loopthrough":
155                                         self.linkNIMs(sec, x, int(nim.connectedTo.value))
156                                         connto = self.getRoot(x, int(nim.connectedTo.value))
157                                         if not self.linked.has_key(connto):
158                                                 self.linked[connto] = []
159                                         self.linked[connto].append(x)
160                                 elif nim.configMode.value == "satposdepends":
161                                         self.setSatposDepends(sec, x, int(nim.connectedTo.value))
162                                         connto = self.getRoot(x, int(nim.connectedTo.value))
163                                         if not self.satposdepends.has_key(connto):
164                                                 self.satposdepends[connto] = []
165                                         self.satposdepends[connto].append(x)
166
167                 for slot in nim_slots:
168                         x = slot.slot
169                         nim = slot.config
170                         hw = HardwareInfo()
171                         if slot.isCompatible("DVB-S"):
172                                 print "slot: " + str(x) + " configmode: " + str(nim.configMode.value)
173                                 if nim.configMode.value in [ "loopthrough", "satposdepends", "nothing" ]:
174                                         pass
175                                 else:
176                                         sec.setSlotNotLinked(x)
177                                         if nim.configMode.value == "equal":
178                                                 pass
179                                         elif nim.configMode.value == "simple":          #simple config
180                                                 print "diseqcmode: ", nim.diseqcMode.value
181                                                 if nim.diseqcMode.value == "single":                    #single
182                                                         if nim.simpleSingleSendDiSEqC.value:
183                                                                 self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcA.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.AA, diseqc13V = nim.diseqc13V.value)
184                                                         else:
185                                                                 self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcA.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.NONE, diseqcpos = diseqcParam.SENDNO, diseqc13V = nim.diseqc13V.value)
186                                                 elif nim.diseqcMode.value == "toneburst_a_b":           #Toneburst A/B
187                                                         self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcA.orbital_position, toneburstmode = diseqcParam.A, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.SENDNO, diseqc13V = nim.diseqc13V.value)
188                                                         self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcB.orbital_position, toneburstmode = diseqcParam.B, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.SENDNO, diseqc13V = nim.diseqc13V.value)
189                                                 elif nim.diseqcMode.value == "diseqc_a_b":              #DiSEqC A/B
190                                                         fastDiSEqC = nim.simpleDiSEqCOnlyOnSatChange.value
191                                                         setVoltageTone = nim.simpleDiSEqCSetVoltageTone.value
192                                                         self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcA.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.AA, fastDiSEqC = fastDiSEqC, setVoltageTone = setVoltageTone, diseqc13V = nim.diseqc13V.value)
193                                                         self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcB.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.AB, fastDiSEqC = fastDiSEqC, setVoltageTone = setVoltageTone, diseqc13V = nim.diseqc13V.value)
194                                                 elif nim.diseqcMode.value == "diseqc_a_b_c_d":          #DiSEqC A/B/C/D
195                                                         fastDiSEqC = nim.simpleDiSEqCOnlyOnSatChange.value
196                                                         setVoltageTone = nim.simpleDiSEqCSetVoltageTone.value
197                                                         self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcA.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.AA, fastDiSEqC = fastDiSEqC, setVoltageTone = setVoltageTone, diseqc13V = nim.diseqc13V.value)
198                                                         self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcB.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.AB, fastDiSEqC = fastDiSEqC, setVoltageTone = setVoltageTone, diseqc13V = nim.diseqc13V.value)
199                                                         self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcC.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.BA, fastDiSEqC = fastDiSEqC, setVoltageTone = setVoltageTone, diseqc13V = nim.diseqc13V.value)
200                                                         self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcD.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.BB, fastDiSEqC = fastDiSEqC, setVoltageTone = setVoltageTone, diseqc13V = nim.diseqc13V.value)
201                                                 elif nim.diseqcMode.value == "positioner":              #Positioner
202                                                         if nim.latitudeOrientation.value == "north":
203                                                                 laValue = rotorParam.NORTH
204                                                         else:
205                                                                 laValue = rotorParam.SOUTH
206                                                         if nim.longitudeOrientation.value == "east":
207                                                                 loValue = rotorParam.EAST
208                                                         else:
209                                                                 loValue = rotorParam.WEST
210                                                         inputPowerDelta=nim.powerThreshold.value
211                                                         useInputPower=False
212                                                         turning_speed=0
213                                                         if nim.powerMeasurement.value:
214                                                                 useInputPower=True
215                                                                 turn_speed_dict = { "fast": rotorParam.FAST, "slow": rotorParam.SLOW }
216                                                                 if turn_speed_dict.has_key(nim.turningSpeed.value):
217                                                                         turning_speed = turn_speed_dict[nim.turningSpeed.value]
218                                                                 else:
219                                                                         beg_time = localtime(nim.fastTurningBegin.value)
220                                                                         end_time = localtime(nim.fastTurningEnd.value)
221                                                                         turning_speed = ((beg_time.tm_hour+1) * 60 + beg_time.tm_min + 1) << 16
222                                                                         turning_speed |= (end_time.tm_hour+1) * 60 + end_time.tm_min + 1
223                                                         self.addLNBSimple(sec, slotid = x, diseqcmode = 3,
224                                                                 longitude = nim.longitude.float,
225                                                                 loDirection = loValue,
226                                                                 latitude = nim.latitude.float,
227                                                                 laDirection = laValue,
228                                                                 turningSpeed = turning_speed,
229                                                                 useInputPower = useInputPower,
230                                                                 inputPowerDelta = inputPowerDelta,
231                                                                 diseqc13V = nim.diseqc13V.value)
232                                         elif nim.configMode.value == "advanced": #advanced config
233                                                 self.updateAdvanced(sec, x)
234                 print "sec config completed"
235
236         def updateAdvanced(self, sec, slotid):
237                 lnbSat = {}
238                 for x in range(1,37):
239                         lnbSat[x] = []
240
241                 #wildcard for all satellites ( for rotor )
242                 for x in range(3601, 3605):
243                         lnb = int(config.Nims[slotid].advanced.sat[x].lnb.value)
244                         if lnb != 0:
245                                 for x in self.NimManager.satList:
246                                         print "add", x[0], "to", lnb
247                                         lnbSat[lnb].append(x[0])
248
249                 for x in self.NimManager.satList:
250                         lnb = int(config.Nims[slotid].advanced.sat[x[0]].lnb.value)
251                         if lnb != 0:
252                                 print "add", x[0], "to", lnb
253                                 lnbSat[lnb].append(x[0])
254
255                 for x in range(1,37):
256                         if len(lnbSat[x]) > 0:
257                                 currLnb = config.Nims[slotid].advanced.lnb[x]
258                                 sec.addLNB()
259
260                                 if x < 33:
261                                         sec.setLNBNum(x)
262
263                                 tunermask = 1 << slotid
264                                 if self.equal.has_key(slotid):
265                                         for slot in self.equal[slotid]:
266                                                 tunermask |= (1 << slot)
267                                 elif self.linked.has_key(slotid):
268                                         for slot in self.linked[slotid]:
269                                                 tunermask |= (1 << slot)
270
271                                 if currLnb.lof.value != "unicable":
272                                         sec.setLNBSatCR(-1)
273
274                                 if currLnb.lof.value == "universal_lnb":
275                                         sec.setLNBLOFL(9750000)
276                                         sec.setLNBLOFH(10600000)
277                                         sec.setLNBThreshold(11700000)
278                                 elif currLnb.lof.value == "unicable":
279                                         sec.setLNBLOFL(9750000)
280                                         sec.setLNBLOFH(10600000)
281                                         sec.setLNBThreshold(11700000)
282                                         if currLnb.unicable.value == "unicable_user":
283                                                 sec.setLNBSatCR(currLnb.satcruser.index)
284                                                 sec.setLNBSatCRvco(currLnb.satcrvcouser[currLnb.satcruser.index].value*1000)
285                                         elif currLnb.unicable.value == "unicable_matrix":
286                                                 manufacturer_name = currLnb.unicableMatrixManufacturer.value
287                                                 manufacturer = currLnb.unicableMatrix[manufacturer_name]
288                                                 product_name = manufacturer.product.value
289                                                 sec.setLNBSatCR(manufacturer.scr[product_name].index)
290                                                 sec.setLNBSatCRvco(manufacturer.vco[product_name][manufacturer.scr[product_name].index].value*1000)
291                                         elif currLnb.unicable.value == "unicable_lnb":
292                                                 manufacturer_name = currLnb.unicableMatrixManufacturer.value
293                                                 manufacturer = currLnb.unicableMatrix[manufacturer_name]
294                                                 product_name = manufacturer.product.value
295                                                 sec.setLNBSatCR(manufacturer.scr[product_name].index)
296                                                 sec.setLNBSatCRvco(manufacturer.vco[product_name][manufacturer.scr[product_name].index].value*1000)
297                                 elif currLnb.lof.value == "c_band":
298                                         sec.setLNBLOFL(5150000)
299                                         sec.setLNBLOFH(5150000)
300                                         sec.setLNBThreshold(5150000)
301                                 elif currLnb.lof.value == "user_defined":
302                                         sec.setLNBLOFL(currLnb.lofl.value * 1000)
303                                         sec.setLNBLOFH(currLnb.lofh.value * 1000)
304                                         sec.setLNBThreshold(currLnb.threshold.value * 1000)
305
306 #                               if currLnb.output_12v.value == "0V":
307 #                                       pass # nyi in drivers
308 #                               elif currLnb.output_12v.value == "12V":
309 #                                       pass # nyi in drivers
310
311                                 if currLnb.increased_voltage.value:
312                                         sec.setLNBIncreasedVoltage(lnbParam.ON)
313                                 else:
314                                         sec.setLNBIncreasedVoltage(lnbParam.OFF)
315
316                                 dm = currLnb.diseqcMode.value
317                                 if dm == "none":
318                                         sec.setDiSEqCMode(diseqcParam.NONE)
319                                 elif dm == "1_0":
320                                         sec.setDiSEqCMode(diseqcParam.V1_0)
321                                 elif dm == "1_1":
322                                         sec.setDiSEqCMode(diseqcParam.V1_1)
323                                 elif dm == "1_2":
324                                         sec.setDiSEqCMode(diseqcParam.V1_2)
325
326                                 if self.satposdepends.has_key(slotid):
327                                         for slot in self.satposdepends[slotid]:
328                                                 tunermask |= (1 << slot)
329
330                                 if dm != "none":
331                                         if currLnb.toneburst.value == "none":
332                                                 sec.setToneburst(diseqcParam.NO)
333                                         elif currLnb.toneburst.value == "A":
334                                                 sec.setToneburst(diseqcParam.A)
335                                         elif currLnb.toneburst.value == "B":
336                                                 sec.setToneburst(diseqcParam.B)
337
338                                         # Committed Diseqc Command
339                                         cdc = currLnb.commitedDiseqcCommand.value
340
341                                         c = { "none": diseqcParam.SENDNO,
342                                                 "AA": diseqcParam.AA,
343                                                 "AB": diseqcParam.AB,
344                                                 "BA": diseqcParam.BA,
345                                                 "BB": diseqcParam.BB }
346
347                                         if c.has_key(cdc):
348                                                 sec.setCommittedCommand(c[cdc])
349                                         else:
350                                                 sec.setCommittedCommand(long(cdc))
351
352                                         sec.setFastDiSEqC(currLnb.fastDiseqc.value)
353
354                                         sec.setSeqRepeat(currLnb.sequenceRepeat.value)
355
356                                         if currLnb.diseqcMode.value == "1_0":
357                                                 currCO = currLnb.commandOrder1_0.value
358                                         else:
359                                                 currCO = currLnb.commandOrder.value
360
361                                                 udc = int(currLnb.uncommittedDiseqcCommand.value)
362                                                 if udc > 0:
363                                                         sec.setUncommittedCommand(0xF0|(udc-1))
364                                                 else:
365                                                         sec.setUncommittedCommand(0) # SENDNO
366
367                                                 sec.setRepeats({"none": 0, "one": 1, "two": 2, "three": 3}[currLnb.diseqcRepeats.value])
368
369                                         setCommandOrder = False
370
371                                         # 0 "committed, toneburst",
372                                         # 1 "toneburst, committed",
373                                         # 2 "committed, uncommitted, toneburst",
374                                         # 3 "toneburst, committed, uncommitted",
375                                         # 4 "uncommitted, committed, toneburst"
376                                         # 5 "toneburst, uncommitted, commmitted"
377                                         order_map = {"ct": 0, "tc": 1, "cut": 2, "tcu": 3, "uct": 4, "tuc": 5}
378                                         sec.setCommandOrder(order_map[currCO])
379
380                                 if dm == "1_2":
381                                         latitude = currLnb.latitude.float
382                                         sec.setLatitude(latitude)
383                                         longitude = currLnb.longitude.float
384                                         sec.setLongitude(longitude)
385                                         if currLnb.latitudeOrientation.value == "north":
386                                                 sec.setLaDirection(rotorParam.NORTH)
387                                         else:
388                                                 sec.setLaDirection(rotorParam.SOUTH)
389                                         if currLnb.longitudeOrientation.value == "east":
390                                                 sec.setLoDirection(rotorParam.EAST)
391                                         else:
392                                                 sec.setLoDirection(rotorParam.WEST)
393
394                                 if currLnb.powerMeasurement.value:
395                                         sec.setUseInputpower(True)
396                                         sec.setInputpowerDelta(currLnb.powerThreshold.value)
397                                         turn_speed_dict = { "fast": rotorParam.FAST, "slow": rotorParam.SLOW }
398                                         if turn_speed_dict.has_key(currLnb.turningSpeed.value):
399                                                 turning_speed = turn_speed_dict[currLnb.turningSpeed.value]
400                                         else:
401                                                 beg_time = localtime(currLnb.fastTurningBegin.value)
402                                                 end_time = localtime(currLnb.fastTurningEnd.value)
403                                                 turning_speed = ((beg_time.tm_hour + 1) * 60 + beg_time.tm_min + 1) << 16
404                                                 turning_speed |= (end_time.tm_hour + 1) * 60 + end_time.tm_min + 1
405                                         sec.setRotorTurningSpeed(turning_speed)
406                                 else:
407                                         sec.setUseInputpower(False)
408
409                                 sec.setLNBSlotMask(tunermask)
410
411                                 sec.setLNBPrio(int(currLnb.prio.value))
412
413                                 # finally add the orbital positions
414                                 for y in lnbSat[x]:
415                                         self.addSatellite(sec, y)
416                                         if x > 32:
417                                                 satpos = x > 32 and (3604-(36 - x)) or y
418                                         else:
419                                                 satpos = y
420                                         currSat = config.Nims[slotid].advanced.sat[satpos]
421                                         if currSat.voltage.value == "polarization":
422                                                 if config.Nims[slotid].diseqc13V.value:
423                                                         sec.setVoltageMode(switchParam.HV_13)
424                                                 else:
425                                                         sec.setVoltageMode(switchParam.HV)
426                                         elif currSat.voltage.value == "13V":
427                                                 sec.setVoltageMode(switchParam._14V)
428                                         elif currSat.voltage.value == "18V":
429                                                 sec.setVoltageMode(switchParam._18V)
430
431                                         if currSat.tonemode.value == "band":
432                                                 sec.setToneMode(switchParam.HILO)
433                                         elif currSat.tonemode.value == "on":
434                                                 sec.setToneMode(switchParam.ON)
435                                         elif currSat.tonemode.value == "off":
436                                                 sec.setToneMode(switchParam.OFF)
437                                                 
438                                         if not currSat.usals.value and x < 34:
439                                                 sec.setRotorPosNum(currSat.rotorposition.value)
440                                         else:
441                                                 sec.setRotorPosNum(0) #USALS
442
443         def __init__(self, nimmgr):
444                 self.NimManager = nimmgr
445                 self.configuredSatellites = Set()
446                 self.update()
447
448 class NIM(object):
449         def __init__(self, slot, type, description, has_outputs = True, internally_connectable = None):
450                 self.slot = slot
451
452                 if type not in ["DVB-S", "DVB-C", "DVB-T", "DVB-S2", None]:
453                         print "warning: unknown NIM type %s, not using." % type
454                         type = None
455
456                 self.type = type
457                 self.description = description
458                 self.has_outputs = has_outputs
459                 self.internally_connectable = internally_connectable
460
461         def isCompatible(self, what):
462                 compatible = {
463                                 None: [None],
464                                 "DVB-S": ["DVB-S", None],
465                                 "DVB-C": ["DVB-C", None],
466                                 "DVB-T": ["DVB-T", None],
467                                 "DVB-S2": ["DVB-S", "DVB-S2", None]
468                         }
469                 return what in compatible[self.type]
470         
471         def connectableTo(self):
472                 connectable = {
473                                 "DVB-S": ["DVB-S", "DVB-S2"],
474                                 "DVB-C": ["DVB-C"],
475                                 "DVB-T": ["DVB-T"],
476                                 "DVB-S2": ["DVB-S", "DVB-S2"]
477                         }
478                 return connectable[self.type]
479
480         def getSlotName(self):
481                 # get a friendly description for a slot name.
482                 # we name them "Tuner A/B/C/...", because that's what's usually written on the back
483                 # of the device.
484                 return _("Tuner ") + chr(ord('A') + self.slot)
485
486         slot_name = property(getSlotName)
487
488         def getSlotID(self):
489                 return chr(ord('A') + self.slot)
490         
491         def hasOutputs(self):
492                 return self.has_outputs
493         
494         def internallyConnectableTo(self):
495                 return self.internally_connectable
496
497         slot_id = property(getSlotID)
498
499         def getFriendlyType(self):
500                 return {
501                         "DVB-S": "DVB-S", 
502                         "DVB-T": "DVB-T",
503                         "DVB-S2": "DVB-S2",
504                         "DVB-C": "DVB-C",
505                         None: _("empty")
506                         }[self.type]
507
508         friendly_type = property(getFriendlyType)
509
510         def getFriendlyFullDescription(self):
511                 nim_text = self.slot_name + ": "
512                         
513                 if self.empty:
514                         nim_text += _("(empty)")
515                 else:
516                         nim_text += self.description + " (" + self.friendly_type + ")"
517                 
518                 return nim_text
519
520         friendly_full_description = property(getFriendlyFullDescription)
521         config_mode = property(lambda self: config.Nims[self.slot].configMode.value)
522         config = property(lambda self: config.Nims[self.slot])
523         empty = property(lambda self: self.type is None)
524
525 class NimManager:
526         def getConfiguredSats(self):
527                 return self.sec.getConfiguredSats()
528
529         def getTransponders(self, pos):
530                 if self.transponders.has_key(pos):
531                         return self.transponders[pos]
532                 else:
533                         return []
534
535         def getTranspondersCable(self, nim):
536                 nimConfig = config.Nims[nim]
537                 if nimConfig.configMode.value != "nothing" and nimConfig.cable.scan_type.value == "provider":
538                         return self.transponderscable[self.cablesList[nimConfig.cable.scan_provider.index][0]]
539                 return [ ]
540
541         def getTranspondersTerrestrial(self, region):
542                 return self.transpondersterrestrial[region]
543         
544         def getCableDescription(self, nim):
545                 return self.cablesList[config.Nims[nim].scan_provider.index][0]
546
547         def getCableFlags(self, nim):
548                 return self.cablesList[config.Nims[nim].scan_provider.index][1]
549
550         def getTerrestrialDescription(self, nim):
551                 return self.terrestrialsList[config.Nims[nim].terrestrial.index][0]
552
553         def getTerrestrialFlags(self, nim):
554                 return self.terrestrialsList[config.Nims[nim].terrestrial.index][1]
555
556         def getSatDescription(self, pos):
557                 return self.satellites[pos]
558
559         def readTransponders(self):
560                 # read initial networks from file. we only read files which we are interested in,
561                 # which means only these where a compatible tuner exists.
562                 self.satellites = { }
563                 self.transponders = { }
564                 self.transponderscable = { }
565                 self.transpondersterrestrial = { }
566                 db = eDVBDB.getInstance()
567                 if self.hasNimType("DVB-S"):
568                         print "Reading satellites.xml"
569                         db.readSatellites(self.satList, self.satellites, self.transponders)
570 #                       print "SATLIST", self.satList
571 #                       print "SATS", self.satellites
572 #                       print "TRANSPONDERS", self.transponders
573
574                 if self.hasNimType("DVB-C"):
575                         print "Reading cables.xml"
576                         db.readCables(self.cablesList, self.transponderscable)
577 #                       print "CABLIST", self.cablesList
578 #                       print "TRANSPONDERS", self.transponders
579
580                 if self.hasNimType("DVB-T"):
581                         print "Reading terrestrial.xml"
582                         db.readTerrestrials(self.terrestrialsList, self.transpondersterrestrial)
583 #                       print "TERLIST", self.terrestrialsList
584 #                       print "TRANSPONDERS", self.transpondersterrestrial
585
586         def enumerateNIMs(self):
587                 # enum available NIMs. This is currently very dreambox-centric and uses the /proc/bus/nim_sockets interface.
588                 # the result will be stored into nim_slots.
589                 # the content of /proc/bus/nim_sockets looks like:
590                 # NIM Socket 0:
591                 #          Type: DVB-S
592                 #          Name: BCM4501 DVB-S2 NIM (internal)
593                 # NIM Socket 1:
594                 #          Type: DVB-S
595                 #          Name: BCM4501 DVB-S2 NIM (internal)
596                 # NIM Socket 2:
597                 #          Type: DVB-T
598                 #          Name: Philips TU1216
599                 # NIM Socket 3:
600                 #          Type: DVB-S
601                 #          Name: Alps BSBE1 702A
602                 
603                 #
604                 # Type will be either "DVB-S", "DVB-S2", "DVB-T", "DVB-C" or None.
605
606                 # nim_slots is an array which has exactly one entry for each slot, even for empty ones.
607                 self.nim_slots = [ ]
608
609                 nimfile = tryOpen("/proc/bus/nim_sockets")
610
611                 if nimfile is None:
612                         return
613
614                 current_slot = None
615
616                 entries = {}
617                 for line in nimfile.readlines():
618                         if line == "":
619                                 break
620                         if line.strip().startswith("NIM Socket"):
621                                 parts = line.strip().split(" ")
622                                 current_slot = int(parts[2][:-1])
623                                 entries[current_slot] = {}
624                         elif line.strip().startswith("Type:"):
625                                 entries[current_slot]["type"] = str(line.strip()[6:])
626                         elif line.strip().startswith("Name:"):
627                                 entries[current_slot]["name"] = str(line.strip()[6:])
628                         elif line.strip().startswith("Has_Outputs:"):
629                                 input = str(line.strip()[len("Has_Outputs:") + 1:])
630                                 entries[current_slot]["has_outputs"] = (input == "yes")
631                         elif line.strip().startswith("Internally_Connectable:"):
632                                 input = int(line.strip()[len("Internally_Connectable:") + 1:])
633                                 entries[current_slot]["internally_connectable"] = input 
634                         elif line.strip().startswith("empty"):
635                                 entries[current_slot]["type"] = None
636                                 entries[current_slot]["name"] = _("N/A")
637                 nimfile.close()
638                 
639                 for id, entry in entries.items():
640                         if not (entry.has_key("name") and entry.has_key("type")):
641                                 entry["name"] =  _("N/A")
642                                 entry["type"] = None
643                         if not (entry.has_key("has_outputs")):
644                                 entry["has_outputs"] = True
645                         if not (entry.has_key("internally_connectable")):
646                                 entry["internally_connectable"] = None
647                         self.nim_slots.append(NIM(slot = id, description = entry["name"], type = entry["type"], has_outputs = entry["has_outputs"], internally_connectable = entry["internally_connectable"]))
648
649         def hasNimType(self, chktype):
650                 for slot in self.nim_slots:
651                         if slot.isCompatible(chktype):
652                                 return True
653                 return False
654         
655         def getNimType(self, slotid):
656                 return self.nim_slots[slotid].type
657         
658         def getNimDescription(self, slotid):
659                 return self.nim_slots[slotid].friendly_full_description
660
661         def getNimListOfType(self, type, exception = -1):
662                 # returns a list of indexes for NIMs compatible to the given type, except for 'exception'
663                 list = []
664                 for x in self.nim_slots:
665                         if x.isCompatible(type) and x.slot != exception:
666                                 list.append(x.slot)
667                 return list
668
669         def __init__(self):
670                 self.satList = [ ]
671                 self.cablesList = []
672                 self.terrestrialsList = []
673                 self.enumerateNIMs()
674                 self.readTransponders()
675                 InitNimManager(self)    #init config stuff
676
677         # get a list with the friendly full description
678         def nimList(self):
679                 list = [ ]
680                 for slot in self.nim_slots:
681                         list.append(slot.friendly_full_description)
682                 return list
683         
684         def getSlotCount(self):
685                 return len(self.nim_slots)
686         
687         def hasOutputs(self, slotid):
688                 return self.nim_slots[slotid].hasOutputs()
689         
690         def canConnectTo(self, slotid):
691                 slots = []
692                 if self.nim_slots[slotid].internallyConnectableTo() is not None:
693                         slots.append(self.nim_slots[slotid].internallyConnectableTo())
694                 for type in self.nim_slots[slotid].connectableTo(): 
695                         for slot in self.getNimListOfType(type, exception = slotid):
696                                 if self.hasOutputs(slot):
697                                         slots.append(slot)
698                 # remove nims, that have a conntectedTo reference on
699                 for testnim in slots[:]:
700                         for nim in self.getNimListOfType("DVB-S", slotid):
701                                 nimConfig = self.getNimConfig(nim)
702                                 if nimConfig.content.items.has_key("configMode") and nimConfig.configMode.value == "loopthrough" and int(nimConfig.connectedTo.value) == testnim:
703                                         slots.remove(testnim)
704                                         break 
705                 slots.sort()
706                 
707                 return slots
708         
709         def canEqualTo(self, slotid):
710                 type = self.getNimType(slotid)
711                 if type == "DVB-S2":
712                         type = "DVB-S"
713                 nimList = self.getNimListOfType(type, slotid)
714                 for nim in nimList[:]:
715                         mode = self.getNimConfig(nim)
716                         if mode.configMode.value == "loopthrough" or mode.configMode.value == "satposdepends":
717                                 nimList.remove(nim)
718                 return nimList
719
720         def canDependOn(self, slotid):
721                 type = self.getNimType(slotid)
722                 if type == "DVB-S2":
723                         type = "DVB-S"
724                 nimList = self.getNimListOfType(type, slotid)
725                 positionerList = []
726                 for nim in nimList[:]:
727                         mode = self.getNimConfig(nim)
728                         nimHaveRotor = mode.configMode.value == "simple" and mode.diseqcMode.value == "positioner"
729                         if not nimHaveRotor and mode.configMode.value == "advanced":
730                                 for x in range(3601, 3605):
731                                         lnb = int(mode.advanced.sat[x].lnb.value)
732                                         if lnb != 0:
733                                                 nimHaveRotor = True
734                                                 break
735                                 if not nimHaveRotor:
736                                         for sat in mode.advanced.sat.values():
737                                                 lnb_num = int(sat.lnb.value)
738                                                 diseqcmode = lnb_num and mode.advanced.lnb[lnb_num].diseqcMode.value or ""
739                                                 if diseqcmode == "1_2":
740                                                         nimHaveRotor = True
741                                                         break
742                         if nimHaveRotor:
743                                 alreadyConnected = False
744                                 for testnim in nimList:
745                                         testmode = self.getNimConfig(testnim)
746                                         if testmode.configMode.value == "satposdepends" and int(testmode.connectedTo.value) == int(nim):
747                                                 alreadyConnected = True
748                                                 break
749                                 if not alreadyConnected:
750                                         positionerList.append(nim)
751                 return positionerList
752         
753         def getNimConfig(self, slotid):
754                 return config.Nims[slotid]
755         
756         def getSatName(self, pos):
757                 for sat in self.satList:
758                         if sat[0] == pos:
759                                 return sat[1]
760                 return _("N/A")
761
762         def getSatList(self):
763                 return self.satList
764
765         def getSatListForNim(self, slotid):
766                 list = []
767                 if self.nim_slots[slotid].isCompatible("DVB-S"):
768                         nim = config.Nims[slotid]
769                         #print "slotid:", slotid
770
771                         #print "self.satellites:", self.satList[config.Nims[slotid].diseqcA.index]
772                         #print "diseqcA:", config.Nims[slotid].diseqcA.value
773                         configMode = nim.configMode.value
774
775                         if configMode == "equal":
776                                 slotid = int(nim.connectedTo.value)
777                                 nim = config.Nims[slotid]
778                                 configMode = nim.configMode.value
779                         elif configMode == "loopthrough":
780                                 slotid = self.sec.getRoot(slotid, int(nim.connectedTo.value))
781                                 nim = config.Nims[slotid]
782                                 configMode = nim.configMode.value
783
784                         if configMode == "simple":
785                                 dm = nim.diseqcMode.value
786                                 if dm in ["single", "toneburst_a_b", "diseqc_a_b", "diseqc_a_b_c_d"]:
787                                         if nim.diseqcA.orbital_position != 3601:
788                                                 list.append(self.satList[nim.diseqcA.index-1])
789                                 if dm in ["toneburst_a_b", "diseqc_a_b", "diseqc_a_b_c_d"]:
790                                         if nim.diseqcB.orbital_position != 3601:
791                                                 list.append(self.satList[nim.diseqcB.index-1])
792                                 if dm == "diseqc_a_b_c_d":
793                                         if nim.diseqcC.orbital_position != 3601:
794                                                 list.append(self.satList[nim.diseqcC.index-1])
795                                         if nim.diseqcD.orbital_position != 3601:
796                                                 list.append(self.satList[nim.diseqcD.index-1])
797                                 if dm == "positioner":
798                                         for x in self.satList:
799                                                 list.append(x)
800                         elif configMode == "advanced":
801                                 for x in range(3601, 3605):
802                                         if int(nim.advanced.sat[x].lnb.value) != 0:
803                                                 for x in self.satList:
804                                                         list.append(x)
805                                 if not list:
806                                         for x in self.satList:
807                                                 if int(nim.advanced.sat[x[0]].lnb.value) != 0:
808                                                         list.append(x)
809                 return list
810
811         def getRotorSatListForNim(self, slotid):
812                 list = []
813                 if self.nim_slots[slotid].isCompatible("DVB-S"):
814                         #print "slotid:", slotid
815                         #print "self.satellites:", self.satList[config.Nims[slotid].diseqcA.value]
816                         #print "diseqcA:", config.Nims[slotid].diseqcA.value
817                         configMode = config.Nims[slotid].configMode.value
818                         if configMode == "simple":
819                                 if config.Nims[slotid].diseqcMode.value == "positioner":
820                                         for x in self.satList:
821                                                 list.append(x)
822                         elif configMode == "advanced":
823                                 nim = config.Nims[slotid]
824                                 for x in range(3601, 3605):
825                                         if int(nim.advanced.sat[x].lnb.value) != 0:
826                                                 for x in self.satList:
827                                                         list.append(x)
828                                 if not list:
829                                         for x in self.satList:
830                                                 lnbnum = int(nim.advanced.sat[x[0]].lnb.value)
831                                                 if lnbnum != 0:
832                                                         lnb = nim.advanced.lnb[lnbnum]
833                                                         if lnb.diseqcMode.value == "1_2":
834                                                                 list.append(x)
835                 return list
836
837 def InitSecParams():
838         config.sec = ConfigSubsection()
839
840         x = ConfigInteger(default=15, limits = (0, 9999))
841         x.addNotifier(lambda configElement: secClass.setParam(secClass.DELAY_AFTER_CONT_TONE, configElement.value))
842         config.sec.delay_after_continuous_tone_change = x
843
844         x = ConfigInteger(default=10, limits = (0, 9999))
845         x.addNotifier(lambda configElement: secClass.setParam(secClass.DELAY_AFTER_FINAL_VOLTAGE_CHANGE, configElement.value))
846         config.sec.delay_after_final_voltage_change = x
847
848         x = ConfigInteger(default=120, limits = (0, 9999))
849         x.addNotifier(lambda configElement: secClass.setParam(secClass.DELAY_BETWEEN_DISEQC_REPEATS, configElement.value))
850         config.sec.delay_between_diseqc_repeats = x
851
852         x = ConfigInteger(default=50, limits = (0, 9999))
853         x.addNotifier(lambda configElement: secClass.setParam(secClass.DELAY_AFTER_LAST_DISEQC_CMD, configElement.value))
854         config.sec.delay_after_last_diseqc_command = x
855
856         x = ConfigInteger(default=50, limits = (0, 9999))
857         x.addNotifier(lambda configElement: secClass.setParam(secClass.DELAY_AFTER_TONEBURST, configElement.value))
858         config.sec.delay_after_toneburst = x
859
860         x = ConfigInteger(default=20, limits = (0, 9999))
861         x.addNotifier(lambda configElement: secClass.setParam(secClass.DELAY_AFTER_VOLTAGE_CHANGE_BEFORE_SWITCH_CMDS, configElement.value))
862         config.sec.delay_after_change_voltage_before_switch_command = x
863
864         x = ConfigInteger(default=200, limits = (0, 9999))
865         x.addNotifier(lambda configElement: secClass.setParam(secClass.DELAY_AFTER_ENABLE_VOLTAGE_BEFORE_SWITCH_CMDS, configElement.value))
866         config.sec.delay_after_enable_voltage_before_switch_command = x
867
868         x = ConfigInteger(default=700, limits = (0, 9999))
869         x.addNotifier(lambda configElement: secClass.setParam(secClass.DELAY_BETWEEN_SWITCH_AND_MOTOR_CMD, configElement.value))
870         config.sec.delay_between_switch_and_motor_command = x
871
872         x = ConfigInteger(default=500, limits = (0, 9999))
873         x.addNotifier(lambda configElement: secClass.setParam(secClass.DELAY_AFTER_VOLTAGE_CHANGE_BEFORE_MEASURE_IDLE_INPUTPOWER, configElement.value))
874         config.sec.delay_after_voltage_change_before_measure_idle_inputpower = x
875
876         x = ConfigInteger(default=750, limits = (0, 9999))
877         x.addNotifier(lambda configElement: secClass.setParam(secClass.DELAY_AFTER_ENABLE_VOLTAGE_BEFORE_MOTOR_CMD, configElement.value))
878         config.sec.delay_after_enable_voltage_before_motor_command = x
879
880         x = ConfigInteger(default=500, limits = (0, 9999))
881         x.addNotifier(lambda configElement: secClass.setParam(secClass.DELAY_AFTER_MOTOR_STOP_CMD, configElement.value))
882         config.sec.delay_after_motor_stop_command = x
883
884         x = ConfigInteger(default=500, limits = (0, 9999))
885         x.addNotifier(lambda configElement: secClass.setParam(secClass.DELAY_AFTER_VOLTAGE_CHANGE_BEFORE_MOTOR_CMD, configElement.value))
886         config.sec.delay_after_voltage_change_before_motor_command = x
887
888         x = ConfigInteger(default=70, limits = (0, 9999))
889         x.addNotifier(lambda configElement: secClass.setParam(secClass.DELAY_BEFORE_SEQUENCE_REPEAT, configElement.value))
890         config.sec.delay_before_sequence_repeat = x
891
892         x = ConfigInteger(default=360, limits = (0, 9999))
893         x.addNotifier(lambda configElement: secClass.setParam(secClass.MOTOR_RUNNING_TIMEOUT, configElement.value))
894         config.sec.motor_running_timeout = x
895
896         x = ConfigInteger(default=1, limits = (0, 5))
897         x.addNotifier(lambda configElement: secClass.setParam(secClass.MOTOR_COMMAND_RETRIES, configElement.value))
898         config.sec.motor_command_retries = x
899
900         x = ConfigInteger(default=50, limits = (0, 9999))
901         x.addNotifier(lambda configElement: secClass.setParam(secClass.DELAY_AFTER_DISEQC_RESET_CMD, configElement.value))
902         config.sec.delay_after_diseqc_reset_cmd = x
903
904         x = ConfigInteger(default=150, limits = (0, 9999))
905         x.addNotifier(lambda configElement: secClass.setParam(secClass.DELAY_AFTER_DISEQC_PERIPHERIAL_POWERON_CMD, configElement.value))
906         config.sec.delay_after_diseqc_peripherial_poweron_cmd = x
907
908 # TODO add support for satpos depending nims to advanced nim configuration
909 # so a second/third/fourth cable from a motorized lnb can used behind a
910 # diseqc 1.0 / diseqc 1.1 / toneburst switch
911 # the C(++) part should can handle this
912 # the configElement should be only visible when diseqc 1.2 is disabled
913
914 def InitNimManager(nimmgr):
915         InitSecParams()
916         hw = HardwareInfo()
917
918         config.Nims = ConfigSubList()
919         for x in range(len(nimmgr.nim_slots)):
920                 config.Nims.append(ConfigSubsection())
921
922         lnb_choices = {
923                 "universal_lnb": _("Universal LNB"),
924                 "unicable": _("Unicable"),
925                 "c_band": _("C-Band"),
926                 "user_defined": _("User defined")}
927         lnb_choices_default = "universal_lnb"
928
929         unicablelnbproducts = {
930                 "Humax": {"150 SCR":["1210","1420","1680","2040"]},
931                 "Inverto": {"IDLP-40UNIQD+S":["1680","1420","2040","1210"]},
932                 "Kathrein": {"UAS481":["1400","1516","1632","1748"]},
933                 "Kreiling": {"KR1440":["1680","1420","2040","1210"]},
934                 "Radix": {"Unicable LNB":["1680","1420","2040","1210"]},
935                 "Wisi": {"OC 05":["1210","1420","1680","2040"]}}
936         UnicableLnbManufacturers = unicablelnbproducts.keys()
937         UnicableLnbManufacturers.sort()
938
939         unicablematrixproducts = {
940                 "Ankaro": {
941                         "UCS 51440":["1400","1632","1284","1516"],
942                         "UCS 51820":["1400","1632","1284","1516","1864","2096","1748","1980"],
943                         "UCS 51840":["1400","1632","1284","1516","1864","2096","1748","1980"],
944                         "UCS 52240":["1400","1632"],
945                         "UCS 52420":["1400","1632","1284","1516"],
946                         "UCS 52440":["1400","1632","1284","1516"],
947                         "UCS 91440":["1400","1632","1284","1516"],
948                         "UCS 91820":["1400","1632","1284","1516","1864","2096","1748","1980"],
949                         "UCS 91840":["1400","1632","1284","1516","1864","2096","1748","1980"],
950                         "UCS 92240":["1400","1632"],
951                         "UCS 92420":["1400","1632","1284","1516"],
952                         "UCS 92440":["1400","1632","1284","1516"]},
953                 "DCT Delta": {
954                         "SUM518":["1284","1400","1516","1632","1748","1864","1980","2096"],
955                         "SUM918":["1284","1400","1516","1632","1748","1864","1980","2096"],
956                         "SUM928":["1284","1400","1516","1632","1748","1864","1980","2096"]},
957                 "Inverto": {
958                         "IDLP-UST11O-CUO1O-8PP":["1076","1178","1280","1382","1484","1586","1688","1790"]},
959                 "Kathrein": {
960                         "EXR501":["1400","1516","1632","1748"],
961                         "EXR551":["1400","1516","1632","1748"],
962                         "EXR552":["1400","1516"]},
963                 "ROTEK": {
964                         "EKL2/1":["1400","1516"],
965                         "EKL2/1E":["0","0","1632","1748"]},
966                 "Smart": {
967                         "DPA 51":["1284","1400","1516","1632","1748","1864","1980","2096"]},
968                 "Technisat": {
969                         "TechniRouter 5/1x8 G":["1284","1400","1516","1632","1748","1864","1980","2096"],
970                         "TechniRouter 5/1x8 K":["1284","1400","1516","1632","1748","1864","1980","2096"],
971                         "TechniRouter 5/2x4 G":["1284","1400","1516","1632"],
972                         "TechniRouter 5/2x4 K":["1284","1400","1516","1632"]},
973                 "Telstar": {
974                         "SCR 5/1x8 G":["1284","1400","1516","1632","1748","1864","1980","2096"],
975                         "SCR 5/1x8 K":["1284","1400","1516","1632","1748","1864","1980","2096"],
976                         "SCR 5/2x4 G":["1284","1400","1516","1632"],
977                         "SCR 5/2x4 K":["1284","1400","1516","1632"]}}
978         UnicableMatrixManufacturers = unicablematrixproducts.keys()
979         UnicableMatrixManufacturers.sort()
980
981         unicable_choices = {
982                 "unicable_lnb": _("Unicable LNB"),
983                 "unicable_matrix": _("Unicable Martix"),
984                 "unicable_user": "Unicable "+_("User defined")}
985         unicable_choices_default = "unicable_lnb"
986
987         unicableLnb = ConfigSubDict()
988         for y in unicablelnbproducts:
989                 products = unicablelnbproducts[y].keys()
990                 products.sort()
991                 unicableLnb[y] = ConfigSubsection()
992                 unicableLnb[y].product = ConfigSelection(choices = products, default = products[0])
993                 unicableLnb[y].scr = ConfigSubDict()
994                 unicableLnb[y].vco = ConfigSubDict()
995                 for z in products:
996                         scrlist = []
997                         vcolist = unicablelnbproducts[y][z]
998                         unicableLnb[y].vco[z] = ConfigSubList()
999                         for cnt in range(1,1+len(vcolist)):
1000                                 scrlist.append(("%d" %cnt,"SCR %d" %cnt))
1001                                 vcofreq = int(vcolist[cnt-1])
1002                                 unicableLnb[y].vco[z].append(ConfigInteger(default=vcofreq, limits = (vcofreq, vcofreq)))
1003                         unicableLnb[y].scr[z] = ConfigSelection(choices = scrlist, default = scrlist[0][0])
1004         
1005         unicableMatrix = ConfigSubDict()
1006         
1007         for y in unicablematrixproducts:
1008                 products = unicablematrixproducts[y].keys()
1009                 products.sort()
1010                 unicableMatrix[y] = ConfigSubsection()
1011                 unicableMatrix[y].product = ConfigSelection(choices = products, default = products[0])
1012                 unicableMatrix[y].scr = ConfigSubDict()
1013                 unicableMatrix[y].vco = ConfigSubDict()
1014                 for z in products:
1015                         scrlist = []
1016                         vcolist = unicablematrixproducts[y][z]
1017                         unicableMatrix[y].vco[z] = ConfigSubList()
1018                         for cnt in range(1,1+len(vcolist)):
1019                                 vcofreq = int(vcolist[cnt-1])
1020                                 if vcofreq == 0:
1021                                         scrlist.append(("%d" %cnt,"SCR %d " %cnt +_("not used")))
1022                                 else:
1023                                         scrlist.append(("%d" %cnt,"SCR %d" %cnt))
1024                                 unicableMatrix[y].vco[z].append(ConfigInteger(default=vcofreq, limits = (vcofreq, vcofreq)))
1025                         unicableMatrix[y].scr[z] = ConfigSelection(choices = scrlist, default = scrlist[0][0])
1026
1027         satcrvcouser = ConfigSubList()
1028         satcrvcouser.append(ConfigInteger(default=1284, limits = (0, 9999)))
1029         satcrvcouser.append(ConfigInteger(default=1400, limits = (0, 9999)))
1030         satcrvcouser.append(ConfigInteger(default=1516, limits = (0, 9999)))
1031         satcrvcouser.append(ConfigInteger(default=1632, limits = (0, 9999)))
1032         satcrvcouser.append(ConfigInteger(default=1748, limits = (0, 9999)))
1033         satcrvcouser.append(ConfigInteger(default=1864, limits = (0, 9999)))
1034         satcrvcouser.append(ConfigInteger(default=1980, limits = (0, 9999)))
1035         satcrvcouser.append(ConfigInteger(default=2096, limits = (0, 9999)))
1036         
1037         prio_list = [ ("-1", _("Auto")) ]
1038         for prio in range(65):
1039                 prio_list.append((str(prio), str(prio)))
1040         for prio in range(14000,14065):
1041                 prio_list.append((str(prio), str(prio)))
1042         for prio in range(19000,19065):
1043                 prio_list.append((str(prio), str(prio)))
1044
1045         for slot in nimmgr.nim_slots:
1046                 x = slot.slot
1047                 nim = config.Nims[x]
1048                 
1049                 if slot.isCompatible("DVB-S"):
1050                         choices = { "nothing": _("nothing connected"),
1051                                         "simple": _("simple"),
1052                                         "advanced": _("advanced")}
1053                         if len(nimmgr.getNimListOfType(slot.type, exception = x)) > 0:
1054                                 choices["equal"] = _("equal to")
1055                                 choices["satposdepends"] = _("second cable of motorized LNB")
1056                         if len(nimmgr.canConnectTo(x)) > 0:
1057                                 choices["loopthrough"] = _("loopthrough to")
1058                         nim.configMode = ConfigSelection(choices = choices, default = "nothing")
1059
1060 #                       for y in nimmgr.nim_slots:
1061 #                               if y.slot == 0:
1062 #                                       if not y.isCompatible("DVB-S"):
1063 #                                               # reset to simple
1064 #                                               nim.configMode.value = "simple"
1065 #                                               nim.configMode.save()
1066
1067                         nim.diseqc13V = ConfigYesNo(default = False)
1068
1069                         nim.diseqcMode = ConfigSelection(
1070                                 choices = [
1071                                         ("single", _("Single")),
1072                                         ("toneburst_a_b", _("Toneburst A/B")),
1073                                         ("diseqc_a_b", _("DiSEqC A/B")),
1074                                         ("diseqc_a_b_c_d", _("DiSEqC A/B/C/D")),
1075                                         ("positioner", _("Positioner"))],
1076                                 default = "diseqc_a_b")
1077
1078                         choices = []
1079                         for id in nimmgr.getNimListOfType("DVB-S"):
1080                                 if id != x:
1081                                         choices.append((str(id), nimmgr.getNimDescription(id)))
1082                         nim.connectedTo = ConfigSelection(choices = choices)
1083                         nim.simpleSingleSendDiSEqC = ConfigYesNo(default=False)
1084                         nim.simpleDiSEqCSetVoltageTone = ConfigYesNo(default=True)
1085                         nim.simpleDiSEqCOnlyOnSatChange = ConfigYesNo(default=False)
1086                         nim.diseqcA = getConfigSatlist(192, [(3601, _('nothing connected'), 1)] + nimmgr.satList)
1087                         nim.diseqcB = getConfigSatlist(130, [(3601, _('nothing connected'), 1)] + nimmgr.satList)
1088                         nim.diseqcC = ConfigSatlist(list = [(3601, _('nothing connected'), 1)] + nimmgr.satList)
1089                         nim.diseqcD = ConfigSatlist(list = [(3601, _('nothing connected'), 1)] + nimmgr.satList)
1090                         nim.positionerMode = ConfigSelection(
1091                                 choices = [
1092                                         ("usals", _("USALS")),
1093                                         ("manual", _("manual"))],
1094                                 default = "usals")
1095                         nim.longitude = ConfigFloat(default=[5,100], limits=[(0,359),(0,999)])
1096                         nim.longitudeOrientation = ConfigSelection(choices={"east": _("East"), "west": _("West")}, default = "east")
1097                         nim.latitude = ConfigFloat(default=[50,767], limits=[(0,359),(0,999)])
1098                         nim.latitudeOrientation = ConfigSelection(choices={"north": _("North"), "south": _("South")}, default="north")
1099                         nim.powerMeasurement = ConfigYesNo(default=True)
1100                         nim.powerThreshold = ConfigInteger(default=hw.get_device_name() == "dm8000" and 15 or 50, limits=(0, 100))
1101                         nim.turningSpeed = ConfigSelection(choices = [("fast", _("Fast")), ("slow", _("Slow")), ("fast epoch", _("Fast epoch")) ], default = "fast")
1102                         btime = datetime(1970, 1, 1, 7, 0);
1103                         nim.fastTurningBegin = ConfigDateTime(default = mktime(btime.timetuple()), formatstring = _("%H:%M"), increment = 900)
1104                         etime = datetime(1970, 1, 1, 19, 0);
1105                         nim.fastTurningEnd = ConfigDateTime(default = mktime(etime.timetuple()), formatstring = _("%H:%M"), increment = 900)
1106
1107                         # advanced config:
1108                         nim.advanced = ConfigSubsection()
1109                         tmp = [(3601, _('All Satellites')+' 1', 1), (3602, _('All Satellites')+' 2', 1), (3603, _('All Satellites')+' 3', 1), (3604, _('All Satellites')+' 4', 1)]
1110                         nim.advanced.sats = getConfigSatlist(192,nimmgr.satList+tmp)
1111                         nim.advanced.sat = ConfigSubDict()
1112                         lnbs = [("0", "not available")]
1113                         for y in range(1, 33):
1114                                 lnbs.append((str(y), "LNB " + str(y)))
1115
1116                         for x in nimmgr.satList:
1117                                 nim.advanced.sat[x[0]] = ConfigSubsection()
1118                                 nim.advanced.sat[x[0]].voltage = ConfigSelection(choices={"polarization": _("Polarization"), "13V": _("13 V"), "18V": _("18 V")}, default = "polarization")
1119                                 nim.advanced.sat[x[0]].tonemode = ConfigSelection(choices={"band": _("Band"), "on": _("On"), "off": _("Off")}, default = "band")
1120                                 nim.advanced.sat[x[0]].usals = ConfigYesNo(default=True)
1121                                 nim.advanced.sat[x[0]].rotorposition = ConfigInteger(default=1, limits=(1, 255))
1122                                 nim.advanced.sat[x[0]].lnb = ConfigSelection(choices = lnbs)
1123
1124                         for x in range(3601, 3605):
1125                                 nim.advanced.sat[x] = ConfigSubsection()
1126                                 nim.advanced.sat[x].voltage = ConfigSelection(choices={"polarization": _("Polarization"), "13V": _("13 V"), "18V": _("18 V")}, default = "polarization")
1127                                 nim.advanced.sat[x].tonemode = ConfigSelection(choices={"band": _("Band"), "on": _("On"), "off": _("Off")}, default = "band")
1128                                 nim.advanced.sat[x].usals = ConfigYesNo(default=True)
1129                                 nim.advanced.sat[x].rotorposition = ConfigInteger(default=1, limits=(1, 255))
1130                                 lnbnum = 33+x-3601
1131                                 nim.advanced.sat[x].lnb = ConfigSelection(choices = [("0", "not available"), (str(lnbnum), "LNB %d"%(lnbnum))], default="0")
1132
1133                         csw = [("none", _("None")), ("AA", _("AA")), ("AB", _("AB")), ("BA", _("BA")), ("BB", _("BB"))]
1134                         for y in range(0, 16):
1135                                 csw.append((str(0xF0|y), "Input " + str(y+1)))
1136
1137                         ucsw = [("0", _("None"))]
1138                         for y in range(1, 17):
1139                                 ucsw.append((str(y), "Input " + str(y)))
1140
1141                         nim.advanced.lnb = ConfigSubList()
1142                         nim.advanced.lnb.append(ConfigNothing())
1143                         
1144
1145                         for x in range(1, 37):
1146                                 nim.advanced.lnb.append(ConfigSubsection())
1147                                 nim.advanced.lnb[x].lof = ConfigSelection(choices = lnb_choices, default = lnb_choices_default)
1148
1149                                 nim.advanced.lnb[x].lofl = ConfigInteger(default=9750, limits = (0, 99999))
1150                                 nim.advanced.lnb[x].lofh = ConfigInteger(default=10600, limits = (0, 99999))
1151                                 nim.advanced.lnb[x].threshold = ConfigInteger(default=11700, limits = (0, 99999))
1152
1153                                 nim.advanced.lnb[x].unicable = ConfigSelection(choices = unicable_choices, default = unicable_choices_default)
1154
1155                                 nim.advanced.lnb[x].unicableLnb = unicableLnb
1156                                 nim.advanced.lnb[x].unicableLnbManufacturer = ConfigSelection(choices = UnicableLnbManufacturers, default = UnicableLnbManufacturers[0])
1157                                 
1158                                 nim.advanced.lnb[x].unicableMatrix = unicableMatrix
1159                                 nim.advanced.lnb[x].unicableMatrixManufacturer = ConfigSelection(choices = UnicableMatrixManufacturers, default = UnicableMatrixManufacturers[0])
1160                                 
1161                                 nim.advanced.lnb[x].satcruser = ConfigSelection(choices=[
1162                                         ("1", "SatCR 1"),
1163                                         ("2", "SatCR 2"),
1164                                         ("3", "SatCR 3"),
1165                                         ("4", "SatCR 4"),
1166                                         ("5", "SatCR 5"),
1167                                         ("6", "SatCR 6"),
1168                                         ("7", "SatCR 7"),
1169                                         ("8", "SatCR 8")],
1170                                         default="1")
1171                                 nim.advanced.lnb[x].satcrvcouser = satcrvcouser
1172
1173 #                               nim.advanced.lnb[x].output_12v = ConfigSelection(choices = [("0V", _("0 V")), ("12V", _("12 V"))], default="0V")
1174                                 nim.advanced.lnb[x].increased_voltage = ConfigYesNo(default=False)
1175                                 nim.advanced.lnb[x].toneburst = ConfigSelection(choices = [("none", _("None")), ("A", _("A")), ("B", _("B"))], default = "none")
1176                                 if x > 32:
1177                                         nim.advanced.lnb[x].diseqcMode = ConfigSelection(choices = [("1_2", _("1.2"))], default = "1_2")
1178                                 else:
1179                                         nim.advanced.lnb[x].diseqcMode = ConfigSelection(choices = [("none", _("None")), ("1_0", _("1.0")), ("1_1", _("1.1")), ("1_2", _("1.2"))], default = "none")
1180                                 nim.advanced.lnb[x].commitedDiseqcCommand = ConfigSelection(choices = csw)
1181                                 nim.advanced.lnb[x].fastDiseqc = ConfigYesNo(default=False)
1182                                 nim.advanced.lnb[x].sequenceRepeat = ConfigYesNo(default=False)
1183                                 nim.advanced.lnb[x].commandOrder1_0 = ConfigSelection(choices = [("ct", "committed, toneburst"), ("tc", "toneburst, committed")], default = "ct")
1184                                 nim.advanced.lnb[x].commandOrder = ConfigSelection(choices = [
1185                                                 ("ct", "committed, toneburst"),
1186                                                 ("tc", "toneburst, committed"),
1187                                                 ("cut", "committed, uncommitted, toneburst"),
1188                                                 ("tcu", "toneburst, committed, uncommitted"),
1189                                                 ("uct", "uncommitted, committed, toneburst"),
1190                                                 ("tuc", "toneburst, uncommitted, commmitted")],
1191                                                 default="ct")
1192                                 nim.advanced.lnb[x].uncommittedDiseqcCommand = ConfigSelection(choices = ucsw)
1193                                 nim.advanced.lnb[x].diseqcRepeats = ConfigSelection(choices = [("none", _("None")), ("one", _("One")), ("two", _("Two")), ("three", _("Three"))], default = "none")
1194                                 nim.advanced.lnb[x].longitude = ConfigFloat(default = [5,100], limits = [(0,359),(0,999)])
1195                                 nim.advanced.lnb[x].longitudeOrientation = ConfigSelection(choices = [("east", _("East")), ("west", _("West"))], default = "east")
1196                                 nim.advanced.lnb[x].latitude = ConfigFloat(default = [50,767], limits = [(0,359),(0,999)])
1197                                 nim.advanced.lnb[x].latitudeOrientation = ConfigSelection(choices = [("north", _("North")), ("south", _("South"))], default = "north")
1198                                 nim.advanced.lnb[x].powerMeasurement = ConfigYesNo(default=True)
1199                                 nim.advanced.lnb[x].powerThreshold = ConfigInteger(default=hw.get_device_name() == "dm8000" and 15 or 50, limits=(0, 100))
1200                                 nim.advanced.lnb[x].turningSpeed = ConfigSelection(choices = [("fast", _("Fast")), ("slow", _("Slow")), ("fast epoch", _("Fast epoch"))], default = "fast")
1201                                 btime = datetime(1970, 1, 1, 7, 0);
1202                                 nim.advanced.lnb[x].fastTurningBegin = ConfigDateTime(default=mktime(btime.timetuple()), formatstring = _("%H:%M"), increment = 600)
1203                                 etime = datetime(1970, 1, 1, 19, 0);
1204                                 nim.advanced.lnb[x].fastTurningEnd = ConfigDateTime(default=mktime(etime.timetuple()), formatstring = _("%H:%M"), increment = 600)
1205                                 nim.advanced.lnb[x].prio = ConfigSelection(default="-1", choices=prio_list)
1206                 elif slot.isCompatible("DVB-C"):
1207                         nim.configMode = ConfigSelection(
1208                                 choices = {
1209                                         "enabled": _("enabled"),
1210                                         "nothing": _("nothing connected"),
1211                                         },
1212                                 default = "enabled")
1213                         list = [ ]
1214                         n = 0
1215                         for x in nimmgr.cablesList:
1216                                 list.append((str(n), x[0]))
1217                                 n += 1
1218                         nim.cable = ConfigSubsection()
1219                         possible_scan_types = [("bands", _("Frequency bands")), ("steps", _("Frequency steps"))]
1220                         if n:
1221                                 possible_scan_types.append(("provider", _("Provider")))
1222                                 nim.cable.scan_provider = ConfigSelection(default = "0", choices = list)
1223                         nim.cable.scan_type = ConfigSelection(default = "bands", choices = possible_scan_types)
1224                         nim.cable.scan_band_EU_VHF_I = ConfigYesNo(default = True)
1225                         nim.cable.scan_band_EU_MID = ConfigYesNo(default = True)
1226                         nim.cable.scan_band_EU_VHF_III = ConfigYesNo(default = True)
1227                         nim.cable.scan_band_EU_UHF_IV = ConfigYesNo(default = True)
1228                         nim.cable.scan_band_EU_UHF_V = ConfigYesNo(default = True)
1229                         nim.cable.scan_band_EU_SUPER = ConfigYesNo(default = True)
1230                         nim.cable.scan_band_EU_HYPER = ConfigYesNo(default = True)
1231                         nim.cable.scan_band_US_LOW = ConfigYesNo(default = False)
1232                         nim.cable.scan_band_US_MID = ConfigYesNo(default = False)
1233                         nim.cable.scan_band_US_HIGH = ConfigYesNo(default = False)
1234                         nim.cable.scan_band_US_SUPER = ConfigYesNo(default = False)
1235                         nim.cable.scan_band_US_HYPER = ConfigYesNo(default = False)
1236                         nim.cable.scan_frequency_steps = ConfigInteger(default = 1000, limits = (1000, 10000))
1237                         nim.cable.scan_mod_qam16 = ConfigYesNo(default = False)
1238                         nim.cable.scan_mod_qam32 = ConfigYesNo(default = False)
1239                         nim.cable.scan_mod_qam64 = ConfigYesNo(default = True)
1240                         nim.cable.scan_mod_qam128 = ConfigYesNo(default = False)
1241                         nim.cable.scan_mod_qam256 = ConfigYesNo(default = True)
1242                         nim.cable.scan_sr_6900 = ConfigYesNo(default = True)
1243                         nim.cable.scan_sr_6875 = ConfigYesNo(default = True)
1244                         nim.cable.scan_sr_ext1 = ConfigInteger(default = 0, limits = (0, 7230))
1245                         nim.cable.scan_sr_ext2 = ConfigInteger(default = 0, limits = (0, 7230))
1246                 elif slot.isCompatible("DVB-T"):
1247                         nim.configMode = ConfigSelection(
1248                                 choices = {
1249                                         "enabled": _("enabled"),
1250                                         "nothing": _("nothing connected"),
1251                                         },
1252                                 default = "enabled")
1253                         list = []
1254                         n = 0
1255                         for x in nimmgr.terrestrialsList:
1256                                 list.append((str(n), x[0]))
1257                                 n += 1
1258                         nim.terrestrial = ConfigSelection(choices = list)
1259                         nim.terrestrial_5V = ConfigOnOff()
1260                 else:
1261                         nim.configMode = ConfigSelection(choices = { "nothing": _("disabled") }, default="nothing");
1262                         if slot.type is not None:
1263                                 print "pls add support for this frontend type!", slot.type
1264 #                       assert False
1265
1266         nimmgr.sec = SecConfigure(nimmgr)
1267
1268 nimmanager = NimManager()