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