d5e4b058c276925e8a68e2576e54d6d39c012921
[openblackhole/openblackhole-enigma2.git] / lib / python / Components / NimManager.py
1 from Tools.HardwareInfo import HardwareInfo
2 from Tools.BoundFunction import boundFunction
3
4 from config import config, ConfigSubsection, ConfigSelection, ConfigFloat, \
5         ConfigSatlist, ConfigYesNo, ConfigInteger, ConfigSubList, ConfigNothing, \
6         ConfigSubDict, ConfigOnOff, ConfigDateTime, ConfigText
7
8 from enigma import eDVBSatelliteEquipmentControl as secClass, \
9         eDVBSatelliteLNBParameters as lnbParam, \
10         eDVBSatelliteDiseqcParameters as diseqcParam, \
11         eDVBSatelliteSwitchParameters as switchParam, \
12         eDVBSatelliteRotorParameters as rotorParam, \
13         eDVBResourceManager, eDVBDB, eEnv
14
15 from time import localtime, mktime
16 from datetime import datetime
17
18 from Tools import Directories
19 import xml.etree.cElementTree
20
21 def getConfigSatlist(orbpos, satlist):
22         default_orbpos = None
23         for x in satlist:
24                 if x[0] == orbpos:
25                         default_orbpos = orbpos
26                         break
27         return ConfigSatlist(satlist, default_orbpos)
28
29 class SecConfigure:
30         def getConfiguredSats(self):
31                 return self.configuredSatellites
32
33         def addSatellite(self, sec, orbpos):
34                 sec.addSatellite(orbpos)
35                 self.configuredSatellites.add(orbpos)
36
37         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, CircularLNB = False):
38                 if orbpos is None or orbpos == 3600 or orbpos == 3601:
39                         return
40                 #simple defaults
41                 sec.addLNB()
42                 tunermask = 1 << slotid
43                 if self.equal.has_key(slotid):
44                         for slot in self.equal[slotid]:
45                                 tunermask |= (1 << slot)
46                 if self.linked.has_key(slotid):
47                         for slot in self.linked[slotid]:
48                                 tunermask |= (1 << slot)
49                 sec.setLNBSatCR(-1)
50                 sec.setLNBNum(1)
51                 sec.setLNBLOFL(CircularLNB and 10750000 or 9750000)
52                 sec.setLNBLOFH(CircularLNB and 10750000 or 10600000)
53                 sec.setLNBThreshold(CircularLNB and 10750000 or 11700000)
54                 sec.setLNBIncreasedVoltage(False)
55                 sec.setRepeats(0)
56                 sec.setFastDiSEqC(fastDiSEqC)
57                 sec.setSeqRepeat(False)
58                 sec.setCommandOrder(0)
59
60                 #user values
61
62                 sec.setDiSEqCMode(3 if diseqcmode == 4 else diseqcmode)
63                 sec.setToneburst(toneburstmode)
64                 sec.setCommittedCommand(diseqcpos)
65                 sec.setUncommittedCommand(0) # SENDNO
66
67                 if 0 <= diseqcmode < 3:
68                         self.addSatellite(sec, orbpos)
69                         if setVoltageTone:
70                                 if diseqc13V:
71                                         sec.setVoltageMode(switchParam.HV_13)
72                                 else:
73                                         sec.setVoltageMode(switchParam.HV)
74                                 sec.setToneMode(switchParam.HILO)
75                         else:
76                                 sec.setVoltageMode(switchParam._14V)
77                                 sec.setToneMode(switchParam.OFF)
78                 elif 3 <= diseqcmode < 5: # diseqc 1.2
79                         if self.satposdepends.has_key(slotid):
80                                 for slot in self.satposdepends[slotid]:
81                                         tunermask |= (1 << slot)
82                         sec.setLatitude(latitude)
83                         sec.setLaDirection(laDirection)
84                         sec.setLongitude(longitude)
85                         sec.setLoDirection(loDirection)
86                         sec.setUseInputpower(useInputPower)
87                         sec.setInputpowerDelta(inputPowerDelta)
88                         sec.setRotorTurningSpeed(turningSpeed)
89                         user_satList = self.NimManager.satList
90                         if diseqcmode == 4:
91                                 user_satList = []
92                                 if orbpos and isinstance(orbpos, str):
93                                         orbpos = orbpos.replace("]", "").replace("[", "")
94                                         for user_sat in self.NimManager.satList:
95                                                 sat_str = str(user_sat[0])
96                                                 if ("," not in orbpos and sat_str == orbpos) or ((', ' + sat_str + ',' in orbpos) or (orbpos.startswith(sat_str + ',')) or (orbpos.endswith(', ' + sat_str))):
97                                                         user_satList.append(user_sat)
98                         for x in user_satList:
99                                 print "[SecConfigure] Add sat " + str(x[0])
100                                 self.addSatellite(sec, int(x[0]))
101                                 if diseqc13V:
102                                         sec.setVoltageMode(switchParam.HV_13)
103                                 else:
104                                         sec.setVoltageMode(switchParam.HV)
105                                 sec.setToneMode(switchParam.HILO)
106                                 sec.setRotorPosNum(0) # USALS
107
108                 sec.setLNBSlotMask(tunermask)
109
110         def setSatposDepends(self, sec, nim1, nim2):
111                 print "[SecConfigure] tuner", nim1, "depends on satpos of", nim2
112                 sec.setTunerDepends(nim1, nim2)
113
114         def linkInternally(self, slotid):
115                 nim = self.NimManager.getNim(slotid)
116                 if nim.internallyConnectableTo is not None:
117                         nim.setInternalLink()
118
119         def linkNIMs(self, sec, nim1, nim2):
120                 print "[SecConfigure] link tuner", nim1, "to tuner", nim2
121                 if nim2 == (nim1 - 1):
122                         self.linkInternally(nim1)
123                 sec.setTunerLinked(nim1, nim2)
124
125         def getRoot(self, slotid, connto):
126                 visited = []
127                 while (self.NimManager.getNimConfig(connto).configMode.value in ("satposdepends", "equal", "loopthrough")):
128                         connto = int(self.NimManager.getNimConfig(connto).connectedTo.value)
129                         if connto in visited: # prevent endless loop
130                                 return slotid
131                         visited.append(connto)
132                 return connto
133
134         def update(self):
135                 sec = secClass.getInstance()
136                 self.configuredSatellites = set()
137                 for slotid in self.NimManager.getNimListOfType("DVB-S"):
138                         if self.NimManager.nimInternallyConnectableTo(slotid) is not None:
139                                 self.NimManager.nimRemoveInternalLink(slotid)
140                 sec.clear() ## this do unlinking NIMs too !!
141                 print "[SecConfigure] sec config cleared"
142
143                 self.linked = { }
144                 self.satposdepends = { }
145                 self.equal = { }
146
147                 nim_slots = self.NimManager.nim_slots
148
149                 used_nim_slots = [ ]
150
151                 for slot in nim_slots:
152                         if slot.type is not None:
153                                 used_nim_slots.append((slot.slot, slot.description, slot.config.configMode.value != "nothing" and True or False, slot.isCompatible("DVB-S2"), slot.frontend_id is None and -1 or slot.frontend_id))
154                 eDVBResourceManager.getInstance().setFrontendSlotInformations(used_nim_slots)
155
156                 for slot in nim_slots:
157                         if slot.frontend_id is not None:
158                                 types = [type for type in ["DVB-T2", "DVB-T", "DVB-C", "DVB-S2", "DVB-S", "ATSC"] if eDVBResourceManager.getInstance().frontendIsCompatible(slot.frontend_id, type)]
159                                 if "DVB-T2" in types:
160                                         # DVB-T2 implies DVB-T support
161                                         types.remove("DVB-T")
162                                 if "DVB-S2" in types:
163                                         # DVB-S2 implies DVB-S support
164                                         types.remove("DVB-S")
165                                 if len(types) > 1:
166                                         slot.multi_type = {}
167                                         for type in types:
168                                                 slot.multi_type[str(types.index(type))] = type
169
170                 for slot in nim_slots:
171                         x = slot.slot
172                         nim = slot.config
173                         if slot.isCompatible("DVB-S"):
174                                 # save what nim we link to/are equal to/satposdepends to.
175                                 # this is stored in the *value* (not index!) of the config list
176                                 if nim.configMode.value == "equal":
177                                         connto = self.getRoot(x, int(nim.connectedTo.value))
178                                         if not self.equal.has_key(connto):
179                                                 self.equal[connto] = []
180                                         self.equal[connto].append(x)
181                                 elif nim.configMode.value == "loopthrough":
182                                         self.linkNIMs(sec, x, int(nim.connectedTo.value))
183                                         connto = self.getRoot(x, int(nim.connectedTo.value))
184                                         if not self.linked.has_key(connto):
185                                                 self.linked[connto] = []
186                                         self.linked[connto].append(x)
187                                 elif nim.configMode.value == "satposdepends":
188                                         self.setSatposDepends(sec, x, int(nim.connectedTo.value))
189                                         connto = self.getRoot(x, int(nim.connectedTo.value))
190                                         if not self.satposdepends.has_key(connto):
191                                                 self.satposdepends[connto] = []
192                                         self.satposdepends[connto].append(x)
193
194                 for slot in nim_slots:
195                         x = slot.slot
196                         nim = slot.config
197                         hw = HardwareInfo()
198                         if slot.isCompatible("DVB-S"):
199                                 print "[SecConfigure] slot: " + str(x) + " configmode: " + str(nim.configMode.value)
200                                 if nim.configMode.value in ( "loopthrough", "satposdepends", "nothing" ):
201                                         pass
202                                 else:
203                                         sec.setSlotNotLinked(x)
204                                         if nim.configMode.value == "equal":
205                                                 pass
206                                         elif nim.configMode.value == "simple":          #simple config
207                                                 print "[SecConfigure] diseqcmode: ", nim.diseqcMode.value
208                                                 if nim.diseqcMode.value == "single":                    #single
209                                                         currentCircular = False
210                                                         if nim.diseqcA.value in ("360", "560"): 
211                                                                 currentCircular = nim.simpleDiSEqCSetCircularLNB.value
212                                                         if nim.simpleSingleSendDiSEqC.value:
213                                                                 self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcA.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.AA, diseqc13V = nim.diseqc13V.value, CircularLNB = currentCircular)
214                                                         else:
215                                                                 self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcA.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.NONE, diseqcpos = diseqcParam.SENDNO, diseqc13V = nim.diseqc13V.value, CircularLNB = currentCircular)
216                                                 elif nim.diseqcMode.value == "toneburst_a_b":           #Toneburst A/B
217                                                         self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcA.orbital_position, toneburstmode = diseqcParam.A, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.SENDNO, diseqc13V = nim.diseqc13V.value)
218                                                         self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcB.orbital_position, toneburstmode = diseqcParam.B, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.SENDNO, diseqc13V = nim.diseqc13V.value)
219                                                 elif nim.diseqcMode.value == "diseqc_a_b":              #DiSEqC A/B
220                                                         fastDiSEqC = nim.simpleDiSEqCOnlyOnSatChange.value
221                                                         setVoltageTone = nim.simpleDiSEqCSetVoltageTone.value
222                                                         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)
223                                                         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)
224                                                 elif nim.diseqcMode.value == "diseqc_a_b_c_d":          #DiSEqC A/B/C/D
225                                                         fastDiSEqC = nim.simpleDiSEqCOnlyOnSatChange.value
226                                                         setVoltageTone = nim.simpleDiSEqCSetVoltageTone.value
227                                                         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)
228                                                         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)
229                                                         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)
230                                                         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)
231                                                 elif nim.diseqcMode.value in ("positioner", "positioner_select"):               #Positioner
232                                                         current_mode = 3
233                                                         sat = 0
234                                                         if nim.diseqcMode.value == "positioner_select":
235                                                                 current_mode = 4
236                                                                 sat = nim.userSatellitesList.value
237                                                         if nim.latitudeOrientation.value == "north":
238                                                                 laValue = rotorParam.NORTH
239                                                         else:
240                                                                 laValue = rotorParam.SOUTH
241                                                         if nim.longitudeOrientation.value == "east":
242                                                                 loValue = rotorParam.EAST
243                                                         else:
244                                                                 loValue = rotorParam.WEST
245                                                         inputPowerDelta=nim.powerThreshold.value
246                                                         useInputPower=False
247                                                         turning_speed=0
248                                                         if nim.powerMeasurement.value:
249                                                                 useInputPower=True
250                                                                 turn_speed_dict = { "fast": rotorParam.FAST, "slow": rotorParam.SLOW }
251                                                                 if turn_speed_dict.has_key(nim.turningSpeed.value):
252                                                                         turning_speed = turn_speed_dict[nim.turningSpeed.value]
253                                                                 else:
254                                                                         beg_time = localtime(nim.fastTurningBegin.value)
255                                                                         end_time = localtime(nim.fastTurningEnd.value)
256                                                                         turning_speed = ((beg_time.tm_hour+1) * 60 + beg_time.tm_min + 1) << 16
257                                                                         turning_speed |= (end_time.tm_hour+1) * 60 + end_time.tm_min + 1
258                                                         self.addLNBSimple(sec, slotid = x, diseqcmode = current_mode,
259                                                                 orbpos = sat,
260                                                                 longitude = nim.longitude.float,
261                                                                 loDirection = loValue,
262                                                                 latitude = nim.latitude.float,
263                                                                 laDirection = laValue,
264                                                                 turningSpeed = turning_speed,
265                                                                 useInputPower = useInputPower,
266                                                                 inputPowerDelta = inputPowerDelta,
267                                                                 diseqc13V = nim.diseqc13V.value)
268                                         elif nim.configMode.value == "advanced": #advanced config
269                                                 self.updateAdvanced(sec, x)
270                 print "[SecConfigure] sec config completed"
271
272         def updateAdvanced(self, sec, slotid):
273                 try:
274                         if config.Nims[slotid].advanced.unicableconnected is not None:
275                                 if config.Nims[slotid].advanced.unicableconnected.value == True:
276                                         config.Nims[slotid].advanced.unicableconnectedTo.save_forced = True
277                                         self.linkNIMs(sec, slotid, int(config.Nims[slotid].advanced.unicableconnectedTo.value))
278                                         connto = self.getRoot(slotid, int(config.Nims[slotid].advanced.unicableconnectedTo.value))
279                                         if not self.linked.has_key(connto):
280                                                 self.linked[connto] = []
281                                         self.linked[connto].append(slotid)
282                                 else:
283                                         config.Nims[slotid].advanced.unicableconnectedTo.save_forced = False
284                 except:
285                         pass
286
287                 lnbSat = {}
288                 for x in range(1, 71):
289                         lnbSat[x] = []
290
291                 #wildcard for all satellites ( for rotor )
292                 for x in range(3601, 3605):
293                         lnb = int(config.Nims[slotid].advanced.sat[x].lnb.value)
294                         if lnb != 0:
295                                 for x in self.NimManager.satList:
296                                         print "[SecConfigure] add", x[0], "to", lnb
297                                         lnbSat[lnb].append(x[0])
298
299                 #wildcard for user satellites ( for rotor )
300                 for x in range(3605, 3607):
301                         lnb = int(config.Nims[slotid].advanced.sat[x].lnb.value)
302                         if lnb != 0:
303                                 userSatlist = config.Nims[slotid].advanced.sat[x].userSatellitesList.value
304                                 userSatlist = userSatlist.replace("]", "").replace("[", "")
305                                 for user_sat in self.NimManager.satList:
306                                         sat_str = str(user_sat[0])
307                                         if userSatlist and ("," not in userSatlist and sat_str == userSatlist) or ((', ' + sat_str + ',' in userSatlist) or (userSatlist.startswith(sat_str + ',')) or (userSatlist.endswith(', ' + sat_str))):
308                                                 print "[SecConfigure] add", user_sat[0], "to", lnb
309                                                 lnbSat[lnb].append(user_sat[0])
310
311                 for x in self.NimManager.satList:
312                         lnb = int(config.Nims[slotid].advanced.sat[x[0]].lnb.value)
313                         if lnb != 0:
314                                 print "[SecConfigure] add", x[0], "to", lnb
315                                 lnbSat[lnb].append(x[0])
316
317                 for x in range(1, 71):
318                         if len(lnbSat[x]) > 0:
319                                 currLnb = config.Nims[slotid].advanced.lnb[x]
320                                 sec.addLNB()
321
322                                 if x < 65:
323                                         sec.setLNBNum(x)
324
325                                 tunermask = 1 << slotid
326                                 if self.equal.has_key(slotid):
327                                         for slot in self.equal[slotid]:
328                                                 tunermask |= (1 << slot)
329                                 if self.linked.has_key(slotid):
330                                         for slot in self.linked[slotid]:
331                                                 tunermask |= (1 << slot)
332
333                                 if currLnb.lof.value != "unicable":
334                                         sec.setLNBSatCR(-1)
335
336                                 if currLnb.lof.value == "universal_lnb":
337                                         sec.setLNBLOFL(9750000)
338                                         sec.setLNBLOFH(10600000)
339                                         sec.setLNBThreshold(11700000)
340                                 elif currLnb.lof.value == "unicable":
341                                         def setupUnicable(configManufacturer, ProductDict):
342                                                 manufacturer_name = configManufacturer.value
343                                                 manufacturer = ProductDict[manufacturer_name]
344                                                 product_name = manufacturer.product.value
345                                                 sec.setLNBSatCR(manufacturer.scr[product_name].index)
346                                                 sec.setLNBSatCRvco(manufacturer.vco[product_name][manufacturer.scr[product_name].index].value*1000)
347                                                 sec.setLNBSatCRpositions(manufacturer.positions[product_name][0].value)
348                                                 sec.setLNBLOFL(manufacturer.lofl[product_name][0].value * 1000)
349                                                 sec.setLNBLOFH(manufacturer.lofh[product_name][0].value * 1000)
350                                                 sec.setLNBThreshold(manufacturer.loft[product_name][0].value * 1000)
351                                                 configManufacturer.save_forced = True
352                                                 manufacturer.product.save_forced = True
353                                                 manufacturer.vco[product_name][manufacturer.scr[product_name].index].save_forced = True
354
355                                         if currLnb.unicable.value == "unicable_user":
356 #TODO satpositions for satcruser
357                                                 sec.setLNBLOFL(currLnb.lofl.value * 1000)
358                                                 sec.setLNBLOFH(currLnb.lofh.value * 1000)
359                                                 sec.setLNBThreshold(currLnb.threshold.value * 1000)
360                                                 sec.setLNBSatCR(currLnb.satcruser.index)
361                                                 sec.setLNBSatCRvco(currLnb.satcrvcouser[currLnb.satcruser.index].value*1000)
362                                                 sec.setLNBSatCRpositions(1)     #HACK
363                                         elif currLnb.unicable.value == "unicable_matrix":
364                                                 setupUnicable(currLnb.unicableMatrixManufacturer, currLnb.unicableMatrix)
365                                         elif currLnb.unicable.value == "unicable_lnb":
366                                                 setupUnicable(currLnb.unicableLnbManufacturer, currLnb.unicableLnb)
367                                 elif currLnb.lof.value == "c_band":
368                                         sec.setLNBLOFL(5150000)
369                                         sec.setLNBLOFH(5150000)
370                                         sec.setLNBThreshold(5150000)
371                                 elif currLnb.lof.value == "user_defined":
372                                         sec.setLNBLOFL(currLnb.lofl.value * 1000)
373                                         sec.setLNBLOFH(currLnb.lofh.value * 1000)
374                                         sec.setLNBThreshold(currLnb.threshold.value * 1000)
375                                 elif currLnb.lof.value == "circular_lnb":
376                                         sec.setLNBLOFL(10750000)
377                                         sec.setLNBLOFH(10750000)
378                                         sec.setLNBThreshold(10750000)
379
380                                 if currLnb.increased_voltage.value:
381                                         sec.setLNBIncreasedVoltage(True)
382                                 else:
383                                         sec.setLNBIncreasedVoltage(False)
384
385                                 dm = currLnb.diseqcMode.value
386                                 if dm == "none":
387                                         sec.setDiSEqCMode(diseqcParam.NONE)
388                                 elif dm == "1_0":
389                                         sec.setDiSEqCMode(diseqcParam.V1_0)
390                                 elif dm == "1_1":
391                                         sec.setDiSEqCMode(diseqcParam.V1_1)
392                                 elif dm == "1_2":
393                                         sec.setDiSEqCMode(diseqcParam.V1_2)
394
395                                         if self.satposdepends.has_key(slotid):
396                                                 for slot in self.satposdepends[slotid]:
397                                                         tunermask |= (1 << slot)
398
399                                 if dm != "none":
400                                         if currLnb.toneburst.value == "none":
401                                                 sec.setToneburst(diseqcParam.NO)
402                                         elif currLnb.toneburst.value == "A":
403                                                 sec.setToneburst(diseqcParam.A)
404                                         elif currLnb.toneburst.value == "B":
405                                                 sec.setToneburst(diseqcParam.B)
406
407                                         # Committed Diseqc Command
408                                         cdc = currLnb.commitedDiseqcCommand.value
409
410                                         c = { "none": diseqcParam.SENDNO,
411                                                 "AA": diseqcParam.AA,
412                                                 "AB": diseqcParam.AB,
413                                                 "BA": diseqcParam.BA,
414                                                 "BB": diseqcParam.BB }
415
416                                         if c.has_key(cdc):
417                                                 sec.setCommittedCommand(c[cdc])
418                                         else:
419                                                 sec.setCommittedCommand(long(cdc))
420
421                                         sec.setFastDiSEqC(currLnb.fastDiseqc.value)
422
423                                         sec.setSeqRepeat(currLnb.sequenceRepeat.value)
424
425                                         if currLnb.diseqcMode.value == "1_0":
426                                                 currCO = currLnb.commandOrder1_0.value
427                                                 sec.setRepeats(0)
428                                         else:
429                                                 currCO = currLnb.commandOrder.value
430
431                                                 udc = int(currLnb.uncommittedDiseqcCommand.value)
432                                                 if udc > 0:
433                                                         sec.setUncommittedCommand(0xF0|(udc-1))
434                                                 else:
435                                                         sec.setUncommittedCommand(0) # SENDNO
436
437                                                 sec.setRepeats({"none": 0, "one": 1, "two": 2, "three": 3}[currLnb.diseqcRepeats.value])
438
439                                         setCommandOrder = False
440
441                                         # 0 "committed, toneburst",
442                                         # 1 "toneburst, committed",
443                                         # 2 "committed, uncommitted, toneburst",
444                                         # 3 "toneburst, committed, uncommitted",
445                                         # 4 "uncommitted, committed, toneburst"
446                                         # 5 "toneburst, uncommitted, commmitted"
447                                         order_map = {"ct": 0, "tc": 1, "cut": 2, "tcu": 3, "uct": 4, "tuc": 5}
448                                         sec.setCommandOrder(order_map[currCO])
449
450                                 if dm == "1_2":
451                                         latitude = currLnb.latitude.float
452                                         sec.setLatitude(latitude)
453                                         longitude = currLnb.longitude.float
454                                         sec.setLongitude(longitude)
455                                         if currLnb.latitudeOrientation.value == "north":
456                                                 sec.setLaDirection(rotorParam.NORTH)
457                                         else:
458                                                 sec.setLaDirection(rotorParam.SOUTH)
459                                         if currLnb.longitudeOrientation.value == "east":
460                                                 sec.setLoDirection(rotorParam.EAST)
461                                         else:
462                                                 sec.setLoDirection(rotorParam.WEST)
463
464                                         if currLnb.powerMeasurement.value:
465                                                 sec.setUseInputpower(True)
466                                                 sec.setInputpowerDelta(currLnb.powerThreshold.value)
467                                                 turn_speed_dict = { "fast": rotorParam.FAST, "slow": rotorParam.SLOW }
468                                                 if turn_speed_dict.has_key(currLnb.turningSpeed.value):
469                                                         turning_speed = turn_speed_dict[currLnb.turningSpeed.value]
470                                                 else:
471                                                         beg_time = localtime(currLnb.fastTurningBegin.value)
472                                                         end_time = localtime(currLnb.fastTurningEnd.value)
473                                                         turning_speed = ((beg_time.tm_hour + 1) * 60 + beg_time.tm_min + 1) << 16
474                                                         turning_speed |= (end_time.tm_hour + 1) * 60 + end_time.tm_min + 1
475                                                 sec.setRotorTurningSpeed(turning_speed)
476                                         else:
477                                                 sec.setUseInputpower(False)
478
479                                 sec.setLNBSlotMask(tunermask)
480
481                                 sec.setLNBPrio(int(currLnb.prio.value))
482
483                                 # finally add the orbital positions
484                                 for y in lnbSat[x]:
485                                         self.addSatellite(sec, y)
486                                         if x > 64:
487                                                 satpos = x > 64 and (3606-(70 - x)) or y
488                                         else:
489                                                 satpos = y
490                                         currSat = config.Nims[slotid].advanced.sat[satpos]
491                                         if currSat.voltage.value == "polarization":
492                                                 if config.Nims[slotid].diseqc13V.value:
493                                                         sec.setVoltageMode(switchParam.HV_13)
494                                                 else:
495                                                         sec.setVoltageMode(switchParam.HV)
496                                         elif currSat.voltage.value == "13V":
497                                                 sec.setVoltageMode(switchParam._14V)
498                                         elif currSat.voltage.value == "18V":
499                                                 sec.setVoltageMode(switchParam._18V)
500
501                                         if currSat.tonemode.value == "band":
502                                                 sec.setToneMode(switchParam.HILO)
503                                         elif currSat.tonemode.value == "on":
504                                                 sec.setToneMode(switchParam.ON)
505                                         elif currSat.tonemode.value == "off":
506                                                 sec.setToneMode(switchParam.OFF)
507                                         if not currSat.usals.value and x < 65:
508                                                 sec.setRotorPosNum(currSat.rotorposition.value)
509                                         else:
510                                                 sec.setRotorPosNum(0) #USALS
511
512         def __init__(self, nimmgr):
513                 self.NimManager = nimmgr
514                 self.configuredSatellites = set()
515                 self.update()
516
517 class NIM(object):
518         def __init__(self, slot, type, description, has_outputs = True, internally_connectable = None, multi_type = {}, frontend_id = None, i2c = None, is_empty = False):
519                 self.slot = slot
520
521                 if type not in ("DVB-S", "DVB-C", "DVB-T", "DVB-S2", "DVB-T2", "DVB-C2", "ATSC", None):
522                         print "[NIM] warning: unknown NIM type %s, not using." % type
523                         type = None
524
525                 self.type = type
526                 self.description = description
527                 self.has_outputs = has_outputs
528                 self.internally_connectable = internally_connectable
529                 self.multi_type = multi_type
530                 self.i2c = i2c
531                 self.frontend_id = frontend_id
532                 self.__is_empty = is_empty
533
534                 self.compatible = {
535                                 None: (None,),
536                                 "DVB-S": ("DVB-S", None),
537                                 "DVB-C": ("DVB-C", None),
538                                 "DVB-T": ("DVB-T", None),
539                                 "DVB-S2": ("DVB-S", "DVB-S2", None),
540                                 "DVB-C2": ("DVB-C", "DVB-C2", None),
541                                 "DVB-T2": ("DVB-T", "DVB-T2", None),
542                                 "ATSC": ("ATSC", None),
543                         }
544
545         def isCompatible(self, what):
546                 if not self.isSupported():
547                         return False
548                 return what in self.compatible[self.getType()]
549
550         def canBeCompatible(self, what):
551                 if not self.isSupported():
552                         return False
553                 if self.isCompatible(what):
554                         return True
555                 for type in self.multi_type.values():
556                         if what in self.compatible[type]:
557                                 return True
558                 return False
559
560         def getType(self):
561                 try:
562                         if self.isMultiType():
563                                 return self.multi_type[self.config.multiType.value]
564                 except:
565                         pass
566                 return self.type
567
568         def connectableTo(self):
569                 connectable = {
570                                 "DVB-S": ("DVB-S", "DVB-S2"),
571                                 "DVB-C": ("DVB-C", "DVB-C2"),
572                                 "DVB-T": ("DVB-T","DVB-T2"),
573                                 "DVB-S2": ("DVB-S", "DVB-S2"),
574                                 "DVB-C2": ("DVB-C", "DVB-C2"),
575                                 "DVB-T2": ("DVB-T", "DVB-T2"),
576                                 "ATSC": ("ATSC"),
577                         }
578                 return connectable[self.getType()]
579
580         def getSlotName(self):
581                 # get a friendly description for a slot name.
582                 # we name them "Tuner A/B/C/...", because that's what's usually written on the back
583                 # of the device.
584                 return _("Tuner") + " " + chr(ord('A') + self.slot)
585
586         slot_name = property(getSlotName)
587
588         def getSlotID(self):
589                 return chr(ord('A') + self.slot)
590
591         def getI2C(self):
592                 return self.i2c
593
594         def hasOutputs(self):
595                 return self.has_outputs
596
597         def internallyConnectableTo(self):
598                 return self.internally_connectable
599
600         def setInternalLink(self):
601                 if self.internally_connectable is not None:
602                         print "[NIM] setting internal link on frontend id", self.frontend_id
603                         open("/proc/stb/frontend/%d/rf_switch" % self.frontend_id, "w").write("internal")
604
605         def removeInternalLink(self):
606                 if self.internally_connectable is not None:
607                         print "[NIM] removing internal link on frontend id", self.frontend_id
608                         open("/proc/stb/frontend/%d/rf_switch" % self.frontend_id, "w").write("external")
609
610         def isMultiType(self):
611                 return (len(self.multi_type) > 0)
612
613         def isEmpty(self):
614                 return self.__is_empty
615
616         # empty tuners are supported!
617         def isSupported(self):
618                 return (self.frontend_id is not None) or self.__is_empty
619
620         # returns dict {<slotid>: <type>}
621         def getMultiTypeList(self):
622                 return self.multi_type
623
624         slot_id = property(getSlotID)
625
626         def getFriendlyType(self):
627                 return {
628                         "DVB-S": "DVB-S",
629                         "DVB-T": "DVB-T",
630                         "DVB-C": "DVB-C",
631                         "DVB-S2": "DVB-S2",
632                         "DVB-T2": "DVB-T2",
633                         "DVB-C2": "DVB-C2",
634                         "ATSC": "ATSC",
635                         None: _("empty")
636                         }[self.getType()]
637
638         friendly_type = property(getFriendlyType)
639
640         def getFriendlyFullDescription(self):
641                 nim_text = self.slot_name + ": "
642
643                 if self.empty:
644                         nim_text += _("(empty)")
645                 elif not self.isSupported():
646                         nim_text += self.description + " (" + _("not supported") + ")"
647                 else:
648                         nim_text += self.description + " (" + self.friendly_type + ")"
649
650                 return nim_text
651
652         friendly_full_description = property(getFriendlyFullDescription)
653         config_mode = property(lambda self: config.Nims[self.slot].configMode.value)
654         config = property(lambda self: config.Nims[self.slot])
655         empty = property(lambda self: self.getType is None)
656
657 class NimManager:
658         def getConfiguredSats(self):
659                 return self.sec.getConfiguredSats()
660
661         def getTransponders(self, pos):
662                 if self.transponders.has_key(pos):
663                         return self.transponders[pos]
664                 else:
665                         return []
666
667         def getTranspondersCable(self, nim):
668                 nimConfig = config.Nims[nim]
669                 if nimConfig.configMode.value != "nothing" and nimConfig.cable.scan_type.value == "provider":
670                         return self.transponderscable[self.cablesList[nimConfig.cable.scan_provider.index][0]]
671                 return [ ]
672
673         def getTranspondersTerrestrial(self, region):
674                 return self.transpondersterrestrial[region]
675
676         def getCableDescription(self, nim):
677                 return self.cablesList[config.Nims[nim].scan_provider.index][0]
678
679         def getCableFlags(self, nim):
680                 return self.cablesList[config.Nims[nim].scan_provider.index][1]
681
682         def getTerrestrialDescription(self, nim):
683                 return self.terrestrialsList[config.Nims[nim].terrestrial.index][0]
684
685         def getTerrestrialFlags(self, nim):
686                 return self.terrestrialsList[config.Nims[nim].terrestrial.index][1]
687
688         def getSatDescription(self, pos):
689                 return self.satellites[pos]
690
691         def sortFunc(self, x):
692                 orbpos = x[0]
693                 if orbpos > 1800:
694                         return orbpos - 3600
695                 else:
696                         return orbpos + 1800
697
698         def readTransponders(self):
699                 self.satellites = { }
700                 self.transponders = { }
701                 self.transponderscable = { }
702                 self.transpondersterrestrial = { }
703                 self.transpondersatsc = { }
704                 db = eDVBDB.getInstance()
705
706                 if self.hasNimType("DVB-S"):
707                         print "[NimManager] Reading satellites.xml"
708                         db.readSatellites(self.satList, self.satellites, self.transponders)
709                         self.satList.sort() # sort by orbpos
710
711                 if self.hasNimType("DVB-C") or self.hasNimType("DVB-T"):
712                         print "[NimManager] Reading cables.xml"
713                         db.readCables(self.cablesList, self.transponderscable)
714                         print "[NimManager] Reading terrestrial.xml"
715                         db.readTerrestrials(self.terrestrialsList, self.transpondersterrestrial)
716
717         def enumerateNIMs(self):
718                 # enum available NIMs. This is currently very dreambox-centric and uses the /proc/bus/nim_sockets interface.
719                 # the result will be stored into nim_slots.
720                 # the content of /proc/bus/nim_sockets looks like:
721                 # NIM Socket 0:
722                 #          Type: DVB-S
723                 #          Name: BCM4501 DVB-S2 NIM (internal)
724                 # NIM Socket 1:
725                 #          Type: DVB-S
726                 #          Name: BCM4501 DVB-S2 NIM (internal)
727                 # NIM Socket 2:
728                 #          Type: DVB-T
729                 #          Name: Philips TU1216
730                 # NIM Socket 3:
731                 #          Type: DVB-S
732                 #          Name: Alps BSBE1 702A
733
734                 #
735                 # Type will be either "DVB-S", "DVB-S2", "DVB-T", "DVB-C" or None.
736
737                 # nim_slots is an array which has exactly one entry for each slot, even for empty ones.
738                 self.nim_slots = [ ]
739
740                 try:
741                         nimfile = open("/proc/bus/nim_sockets")
742                 except IOError:
743                         return
744
745                 current_slot = None
746
747                 entries = {}
748                 for line in nimfile:
749                         if not line:
750                                 break
751                         line = line.strip()
752                         if line.startswith("NIM Socket"):
753                                 parts = line.split(" ")
754                                 current_slot = int(parts[2][:-1])
755                                 entries[current_slot] = {}
756                         elif line.startswith("Type:"):
757                                 entries[current_slot]["type"] = str(line[6:])
758                                 entries[current_slot]["isempty"] = False
759                         elif line.startswith("Name:"):
760                                 entries[current_slot]["name"] = str(line[6:])
761                                 entries[current_slot]["isempty"] = False
762                         elif line.startswith("Has_Outputs:"):
763                                 input = str(line[len("Has_Outputs:") + 1:])
764                                 entries[current_slot]["has_outputs"] = (input == "yes")
765                         elif line.startswith("Internally_Connectable:"):
766                                 input = int(line[len("Internally_Connectable:") + 1:])
767                                 entries[current_slot]["internally_connectable"] = input
768                         elif line.startswith("Frontend_Device:"):
769                                 input = int(line[len("Frontend_Device:") + 1:])
770                                 entries[current_slot]["frontend_device"] = input
771                         elif  line.startswith("Mode"):
772                                 # "Mode 0: DVB-T" -> ["Mode 0", "DVB-T"]
773                                 split = line.split(": ")
774                                 if len(split) > 1 and split[1]:
775                                         # "Mode 0" -> ["Mode", "0"]
776                                         split2 = split[0].split(" ")
777                                         modes = entries[current_slot].get("multi_type", {})
778                                         modes[split2[1]] = split[1].strip()
779                                         entries[current_slot]["multi_type"] = modes
780                         elif line.startswith("I2C_Device:"):
781                                 input = int(line[len("I2C_Device:") + 1:])
782                                 entries[current_slot]["i2c"] = input
783                         elif line.startswith("empty"):
784                                 entries[current_slot]["type"] = None
785                                 entries[current_slot]["name"] = _("N/A")
786                                 entries[current_slot]["isempty"] = True
787                 nimfile.close()
788
789                 from os import path
790
791                 for id, entry in entries.items():
792                         if not (entry.has_key("name") and entry.has_key("type")):
793                                 entry["name"] =  _("N/A")
794                                 entry["type"] = None
795                         if not (entry.has_key("i2c")):
796                                 entry["i2c"] = None
797                         if not (entry.has_key("has_outputs")):
798                                 entry["has_outputs"] = True
799                         if entry.has_key("frontend_device"): # check if internally connectable
800                                 if path.exists("/proc/stb/frontend/%d/rf_switch" % entry["frontend_device"]):
801                                         entry["internally_connectable"] = entry["frontend_device"] - 1
802                                 else:
803                                         entry["internally_connectable"] = None
804                         else:
805                                 entry["frontend_device"] = entry["internally_connectable"] = None
806                         if not (entry.has_key("multi_type")):
807                                 entry["multi_type"] = {}
808                         self.nim_slots.append(NIM(slot = id, description = entry["name"], type = entry["type"], has_outputs = entry["has_outputs"], internally_connectable = entry["internally_connectable"], multi_type = entry["multi_type"], frontend_id = entry["frontend_device"], i2c = entry["i2c"], is_empty = entry["isempty"]))
809
810         def hasNimType(self, chktype):
811                 for slot in self.nim_slots:
812                         if slot.isCompatible(chktype):
813                                 return True
814                         for type in slot.getMultiTypeList().values():
815                                 if chktype == type:
816                                         return True
817                 return False
818
819         def getNimType(self, slotid):
820                 return self.nim_slots[slotid].type
821
822         def getNimDescription(self, slotid):
823                 return self.nim_slots[slotid].friendly_full_description
824
825         def getNimName(self, slotid):
826                 return self.nim_slots[slotid].description
827
828         def getNim(self, slotid):
829                 return self.nim_slots[slotid]
830
831         def getI2CDevice(self, slotid):
832                 return self.nim_slots[slotid].getI2C()
833
834         def getNimListOfType(self, type, exception = -1):
835                 # returns a list of indexes for NIMs compatible to the given type, except for 'exception'
836                 list = []
837                 for x in self.nim_slots:
838                         if x.isCompatible(type) and x.slot != exception:
839                                 list.append(x.slot)
840                 return list
841
842         def __init__(self):
843                 self.satList = [ ]
844                 self.cablesList = []
845                 self.terrestrialsList = []
846                 self.atscList = []
847                 self.enumerateNIMs()
848                 self.readTransponders()
849                 InitNimManager(self)    #init config stuff
850
851         # get a list with the friendly full description
852         def nimList(self):
853                 list = [ ]
854                 for slot in self.nim_slots:
855                         list.append(slot.friendly_full_description)
856                 return list
857
858         def getSlotCount(self):
859                 return len(self.nim_slots)
860
861         def hasOutputs(self, slotid):
862                 return self.nim_slots[slotid].hasOutputs()
863
864         def nimInternallyConnectableTo(self, slotid):
865                 return self.nim_slots[slotid].internallyConnectableTo()
866
867         def nimRemoveInternalLink(self, slotid):
868                 self.nim_slots[slotid].removeInternalLink()
869
870         def canConnectTo(self, slotid):
871                 slots = []
872                 if self.nim_slots[slotid].internallyConnectableTo() is not None:
873                         slots.append(self.nim_slots[slotid].internallyConnectableTo())
874                 for type in self.nim_slots[slotid].connectableTo():
875                         for slot in self.getNimListOfType(type, exception = slotid):
876                                 if self.hasOutputs(slot):
877                                         slots.append(slot)
878                 # remove nims, that have a conntectedTo reference on
879                 for testnim in slots[:]:
880                         for nim in self.getNimListOfType("DVB-S", slotid):
881                                 nimConfig = self.getNimConfig(nim)
882                                 if nimConfig.content.items.has_key("configMode") and nimConfig.configMode.value == "loopthrough" and int(nimConfig.connectedTo.value) == testnim:
883                                         slots.remove(testnim)
884                                         break
885                 slots.sort()
886                 return slots
887
888         def canEqualTo(self, slotid):
889                 type = self.getNimType(slotid)
890                 type = type[:5] # DVB-S2 --> DVB-S, DVB-T2 --> DVB-T, DVB-C2 --> DVB-C
891                 nimList = self.getNimListOfType(type, slotid)
892                 for nim in nimList[:]:
893                         mode = self.getNimConfig(nim)
894                         if mode.configMode.value == "loopthrough" or mode.configMode.value == "satposdepends":
895                                 nimList.remove(nim)
896                 return nimList
897
898         def canDependOn(self, slotid):
899                 type = self.getNimType(slotid)
900                 type = type[:5] # DVB-S2 --> DVB-S, DVB-T2 --> DVB-T, DVB-C2 --> DVB-C
901                 nimList = self.getNimListOfType(type, slotid)
902                 positionerList = []
903                 for nim in nimList[:]:
904                         mode = self.getNimConfig(nim)
905                         nimHaveRotor = mode.configMode.value == "simple" and mode.diseqcMode.value  in ("positioner", "positioner_select")
906                         if not nimHaveRotor and mode.configMode.value == "advanced":
907                                 for x in range(3601, 3607):
908                                         lnb = int(mode.advanced.sat[x].lnb.value)
909                                         if lnb != 0:
910                                                 nimHaveRotor = True
911                                                 break
912                                 if not nimHaveRotor:
913                                         for sat in mode.advanced.sat.values():
914                                                 lnb_num = int(sat.lnb.value)
915                                                 diseqcmode = lnb_num and mode.advanced.lnb[lnb_num].diseqcMode.value or ""
916                                                 if diseqcmode == "1_2":
917                                                         nimHaveRotor = True
918                                                         break
919                         if nimHaveRotor:
920                                 alreadyConnected = False
921                                 for testnim in nimList:
922                                         testmode = self.getNimConfig(testnim)
923                                         if testmode.configMode.value == "satposdepends" and int(testmode.connectedTo.value) == int(nim):
924                                                 alreadyConnected = True
925                                                 break
926                                 if not alreadyConnected:
927                                         positionerList.append(nim)
928                 return positionerList
929
930         def getNimConfig(self, slotid):
931                 return config.Nims[slotid]
932
933         def getSatName(self, pos):
934                 for sat in self.satList:
935                         if sat[0] == pos:
936                                 return sat[1]
937                 return _("N/A")
938
939         def getSatList(self):
940                 return self.satList
941
942         # returns True if something is configured to be connected to this nim
943         # if slotid == -1, returns if something is connected to ANY nim
944         def somethingConnected(self, slotid = -1):
945                 if (slotid == -1):
946                         connected = False
947                         for id in range(self.getSlotCount()):
948                                 if self.somethingConnected(id):
949                                         connected = True
950                         return connected
951                 else:
952                         nim = config.Nims[slotid]
953                         configMode = nim.configMode.value
954
955                         if self.nim_slots[slotid].isCompatible("DVB-S") or self.nim_slots[slotid].isCompatible("DVB-T") or self.nim_slots[slotid].isCompatible("DVB-C"):
956                                 return not (configMode == "nothing")
957
958         def getSatListForNim(self, slotid):
959                 list = []
960                 if self.nim_slots[slotid].isCompatible("DVB-S"):
961                         nim = config.Nims[slotid]
962                         #print "slotid:", slotid
963
964                         #print "self.satellites:", self.satList[config.Nims[slotid].diseqcA.index]
965                         #print "diseqcA:", config.Nims[slotid].diseqcA.value
966                         configMode = nim.configMode.value
967
968                         if configMode == "equal":
969                                 slotid = int(nim.connectedTo.value)
970                                 nim = config.Nims[slotid]
971                                 configMode = nim.configMode.value
972                         elif configMode == "loopthrough":
973                                 slotid = self.sec.getRoot(slotid, int(nim.connectedTo.value))
974                                 nim = config.Nims[slotid]
975                                 configMode = nim.configMode.value
976
977                         if configMode == "simple":
978                                 dm = nim.diseqcMode.value
979                                 if dm in ("single", "toneburst_a_b", "diseqc_a_b", "diseqc_a_b_c_d"):
980                                         if nim.diseqcA.orbital_position < 3600:
981                                                 list.append(self.satList[nim.diseqcA.index - 2])
982                                 if dm in ("toneburst_a_b", "diseqc_a_b", "diseqc_a_b_c_d"):
983                                         if nim.diseqcB.orbital_position < 3600:
984                                                 list.append(self.satList[nim.diseqcB.index - 2])
985                                 if dm == "diseqc_a_b_c_d":
986                                         if nim.diseqcC.orbital_position < 3600:
987                                                 list.append(self.satList[nim.diseqcC.index - 2])
988                                         if nim.diseqcD.orbital_position < 3600:
989                                                 list.append(self.satList[nim.diseqcD.index - 2])
990                                 if dm == "positioner":
991                                         for x in self.satList:
992                                                 list.append(x)
993                                 if dm == "positioner_select": 
994                                         userSatlist = nim.userSatellitesList.value
995                                         userSatlist = userSatlist.replace("]", "").replace("[", "")
996                                         for x in self.satList:
997                                                 sat_str = str(x[0])
998                                                 if userSatlist and ("," not in userSatlist and sat_str == userSatlist) or ((', ' + sat_str + ',' in userSatlist) or (userSatlist.startswith(sat_str + ',')) or (userSatlist.endswith(', ' + sat_str))):
999                                                         list.append(x)
1000                         elif configMode == "advanced":
1001                                 for x in range(3601, 3605):
1002                                         if int(nim.advanced.sat[x].lnb.value) != 0:
1003                                                 for x in self.satList:
1004                                                         list.append(x)
1005                                 if not list:
1006                                         for x in self.satList:
1007                                                 if int(nim.advanced.sat[x[0]].lnb.value) != 0:
1008                                                         list.append(x)
1009                                 for x in range(3605, 3607):
1010                                         if int(nim.advanced.sat[x].lnb.value) != 0:
1011                                                 userSatlist = nim.advanced.sat[x].userSatellitesList.value
1012                                                 userSatlist = userSatlist.replace("]", "").replace("[", "")
1013                                                 for user_sat in self.satList:
1014                                                         sat_str = str(user_sat[0])
1015                                                         if userSatlist and ("," not in userSatlist and sat_str == userSatlist) or ((', ' + sat_str + ',' in userSatlist) or (userSatlist.startswith(sat_str + ',')) or (userSatlist.endswith(', ' + sat_str))) and user_sat not in list:
1016                                                                 list.append(user_sat)
1017                 return list
1018
1019         def getRotorSatListForNim(self, slotid):
1020                 list = []
1021                 if self.nim_slots[slotid].isCompatible("DVB-S"):
1022                         nim = config.Nims[slotid]
1023                         configMode = nim.configMode.value
1024                         if configMode == "simple":
1025                                 if nim.diseqcMode.value == "positioner":
1026                                         for x in self.satList:
1027                                                 list.append(x)
1028                                 elif nim.diseqcMode.value == "positioner_select":
1029                                         userSatlist = nim.userSatellitesList.value
1030                                         userSatlist = userSatlist.replace("]", "").replace("[", "")
1031                                         for x in self.satList:
1032                                                 sat_str = str(x[0])
1033                                                 if userSatlist and ("," not in userSatlist and sat_str == userSatlist) or ((', ' + sat_str + ',' in userSatlist) or (userSatlist.startswith(sat_str + ',')) or (userSatlist.endswith(', ' + sat_str))):
1034                                                         list.append(x)
1035                         elif configMode == "advanced":
1036                                 for x in range(3601, 3605):
1037                                         if int(nim.advanced.sat[x].lnb.value) != 0:
1038                                                 for x in self.satList:
1039                                                         list.append(x)
1040                                 if not list:
1041                                         for x in self.satList:
1042                                                 lnbnum = int(nim.advanced.sat[x[0]].lnb.value)
1043                                                 if lnbnum != 0:
1044                                                         lnb = nim.advanced.lnb[lnbnum]
1045                                                         if lnb.diseqcMode.value == "1_2":
1046                                                                 list.append(x)
1047                                 for x in range(3605, 3607):
1048                                         if int(nim.advanced.sat[x].lnb.value) != 0:
1049                                                 userSatlist = nim.advanced.sat[x].userSatellitesList.value
1050                                                 userSatlist = userSatlist.replace("]", "").replace("[", "")
1051                                                 for user_sat in self.satList:
1052                                                         sat_str = str(user_sat[0])
1053                                                         if userSatlist and ("," not in userSatlist and sat_str == userSatlist) or ((', ' + sat_str + ',' in userSatlist) or (userSatlist.startswith(sat_str + ',')) or (userSatlist.endswith(', ' + sat_str))) and user_sat not in list:
1054                                                                 list.append(user_sat)
1055                 return list
1056
1057 def InitSecParams():
1058         config.sec = ConfigSubsection()
1059
1060         x = ConfigInteger(default=25, limits = (0, 9999))
1061         x.addNotifier(lambda configElement: secClass.setParam(secClass.DELAY_AFTER_CONT_TONE_DISABLE_BEFORE_DISEQC, configElement.value))
1062         config.sec.delay_after_continuous_tone_disable_before_diseqc = x
1063
1064         x = ConfigInteger(default=10, limits = (0, 9999))
1065         x.addNotifier(lambda configElement: secClass.setParam(secClass.DELAY_AFTER_FINAL_CONT_TONE_CHANGE, configElement.value))
1066         config.sec.delay_after_final_continuous_tone_change = x
1067
1068         x = ConfigInteger(default=10, limits = (0, 9999))
1069         x.addNotifier(lambda configElement: secClass.setParam(secClass.DELAY_AFTER_FINAL_VOLTAGE_CHANGE, configElement.value))
1070         config.sec.delay_after_final_voltage_change = x
1071
1072         x = ConfigInteger(default=120, limits = (0, 9999))
1073         x.addNotifier(lambda configElement: secClass.setParam(secClass.DELAY_BETWEEN_DISEQC_REPEATS, configElement.value))
1074         config.sec.delay_between_diseqc_repeats = x
1075
1076         x = ConfigInteger(default=50, limits = (0, 9999))
1077         x.addNotifier(lambda configElement: secClass.setParam(secClass.DELAY_AFTER_LAST_DISEQC_CMD, configElement.value))
1078         config.sec.delay_after_last_diseqc_command = x
1079
1080         x = ConfigInteger(default=50, limits = (0, 9999))
1081         x.addNotifier(lambda configElement: secClass.setParam(secClass.DELAY_AFTER_TONEBURST, configElement.value))
1082         config.sec.delay_after_toneburst = x
1083
1084         x = ConfigInteger(default=20, limits = (0, 9999))
1085         x.addNotifier(lambda configElement: secClass.setParam(secClass.DELAY_AFTER_VOLTAGE_CHANGE_BEFORE_SWITCH_CMDS, configElement.value))
1086         config.sec.delay_after_change_voltage_before_switch_command = x
1087
1088         x = ConfigInteger(default=200, limits = (0, 9999))
1089         x.addNotifier(lambda configElement: secClass.setParam(secClass.DELAY_AFTER_ENABLE_VOLTAGE_BEFORE_SWITCH_CMDS, configElement.value))
1090         config.sec.delay_after_enable_voltage_before_switch_command = x
1091
1092         x = ConfigInteger(default=700, limits = (0, 9999))
1093         x.addNotifier(lambda configElement: secClass.setParam(secClass.DELAY_BETWEEN_SWITCH_AND_MOTOR_CMD, configElement.value))
1094         config.sec.delay_between_switch_and_motor_command = x
1095
1096         x = ConfigInteger(default=500, limits = (0, 9999))
1097         x.addNotifier(lambda configElement: secClass.setParam(secClass.DELAY_AFTER_VOLTAGE_CHANGE_BEFORE_MEASURE_IDLE_INPUTPOWER, configElement.value))
1098         config.sec.delay_after_voltage_change_before_measure_idle_inputpower = x
1099
1100         x = ConfigInteger(default=900, limits = (0, 9999))
1101         x.addNotifier(lambda configElement: secClass.setParam(secClass.DELAY_AFTER_ENABLE_VOLTAGE_BEFORE_MOTOR_CMD, configElement.value))
1102         config.sec.delay_after_enable_voltage_before_motor_command = x
1103
1104         x = ConfigInteger(default=500, limits = (0, 9999))
1105         x.addNotifier(lambda configElement: secClass.setParam(secClass.DELAY_AFTER_MOTOR_STOP_CMD, configElement.value))
1106         config.sec.delay_after_motor_stop_command = x
1107
1108         x = ConfigInteger(default=500, limits = (0, 9999))
1109         x.addNotifier(lambda configElement: secClass.setParam(secClass.DELAY_AFTER_VOLTAGE_CHANGE_BEFORE_MOTOR_CMD, configElement.value))
1110         config.sec.delay_after_voltage_change_before_motor_command = x
1111
1112         x = ConfigInteger(default=70, limits = (0, 9999))
1113         x.addNotifier(lambda configElement: secClass.setParam(secClass.DELAY_BEFORE_SEQUENCE_REPEAT, configElement.value))
1114         config.sec.delay_before_sequence_repeat = x
1115
1116         x = ConfigInteger(default=360, limits = (0, 9999))
1117         x.addNotifier(lambda configElement: secClass.setParam(secClass.MOTOR_RUNNING_TIMEOUT, configElement.value))
1118         config.sec.motor_running_timeout = x
1119
1120         x = ConfigInteger(default=1, limits = (0, 5))
1121         x.addNotifier(lambda configElement: secClass.setParam(secClass.MOTOR_COMMAND_RETRIES, configElement.value))
1122         config.sec.motor_command_retries = x
1123
1124         x = ConfigInteger(default=50, limits = (0, 9999))
1125         x.addNotifier(lambda configElement: secClass.setParam(secClass.DELAY_AFTER_DISEQC_RESET_CMD, configElement.value))
1126         config.sec.delay_after_diseqc_reset_cmd = x
1127
1128         x = ConfigInteger(default=150, limits = (0, 9999))
1129         x.addNotifier(lambda configElement: secClass.setParam(secClass.DELAY_AFTER_DISEQC_PERIPHERIAL_POWERON_CMD, configElement.value))
1130         config.sec.delay_after_diseqc_peripherial_poweron_cmd = x
1131
1132 # TODO add support for satpos depending nims to advanced nim configuration
1133 # so a second/third/fourth cable from a motorized lnb can used behind a
1134 # diseqc 1.0 / diseqc 1.1 / toneburst switch
1135 # the C(++) part should can handle this
1136 # the configElement should be only visible when diseqc 1.2 is disabled
1137
1138 def InitNimManager(nimmgr):
1139         hw = HardwareInfo()
1140         addNimConfig = False
1141         try:
1142                 config.Nims
1143         except:
1144                 addNimConfig = True
1145
1146         if addNimConfig:
1147                 InitSecParams()
1148                 config.Nims = ConfigSubList()
1149                 for x in range(len(nimmgr.nim_slots)):
1150                         config.Nims.append(ConfigSubsection())
1151
1152         lnb_choices = {
1153                 "universal_lnb": _("Universal LNB"),
1154                 "unicable": _("Unicable"),
1155                 "c_band": _("C-Band"),
1156                 "circular_lnb": _("Circular LNB"),
1157                 "user_defined": _("User defined")}
1158
1159         lnb_choices_default = "universal_lnb"
1160
1161         unicablelnbproducts = {}
1162         unicablematrixproducts = {}
1163         doc = xml.etree.cElementTree.parse(eEnv.resolve("${datadir}/enigma2/unicable.xml"))
1164         root = doc.getroot()
1165
1166         entry = root.find("lnb")
1167         for manufacturer in entry.getchildren():
1168                 m={}
1169                 for product in manufacturer.getchildren():
1170                         scr=[]
1171                         lscr=("scr1","scr2","scr3","scr4","scr5","scr6","scr7","scr8")
1172                         for i in range(len(lscr)):
1173                                 scr.append(product.get(lscr[i],"0"))
1174                         for i in range(len(lscr)):
1175                                 if scr[len(lscr)-i-1] == "0":
1176                                         scr.pop()
1177                                 else:
1178                                         break;
1179                         lof=[]
1180                         lof.append(int(product.get("positions",1)))
1181                         lof.append(int(product.get("lofl",9750)))
1182                         lof.append(int(product.get("lofh",10600)))
1183                         lof.append(int(product.get("threshold",11700)))
1184                         scr.append(tuple(lof))
1185                         m.update({product.get("name"):tuple(scr)})
1186                 unicablelnbproducts.update({manufacturer.get("name"):m})
1187
1188         entry = root.find("matrix")
1189         for manufacturer in entry.getchildren():
1190                 m={}
1191                 for product in manufacturer.getchildren():
1192                         scr=[]
1193                         lscr=("scr1","scr2","scr3","scr4","scr5","scr6","scr7","scr8")
1194                         for i in range(len(lscr)):
1195                                 scr.append(product.get(lscr[i],"0"))
1196                         for i in range(len(lscr)):
1197                                 if scr[len(lscr)-i-1] == "0":
1198                                         scr.pop()
1199                                 else:
1200                                         break;
1201                         lof=[]
1202                         lof.append(int(product.get("positions",1)))
1203                         lof.append(int(product.get("lofl",9750)))
1204                         lof.append(int(product.get("lofh",10600)))
1205                         lof.append(int(product.get("threshold",11700)))
1206                         scr.append(tuple(lof))
1207                         m.update({product.get("name"):tuple(scr)})
1208                 unicablematrixproducts.update({manufacturer.get("name"):m})
1209
1210         UnicableLnbManufacturers = unicablelnbproducts.keys()
1211         UnicableLnbManufacturers.sort()
1212         UnicableMatrixManufacturers = unicablematrixproducts.keys()
1213         UnicableMatrixManufacturers.sort()
1214
1215         unicable_choices = {
1216                 "unicable_lnb": _("Unicable LNB"),
1217                 "unicable_matrix": _("Unicable Martix"),
1218                 "unicable_user": "Unicable "+_("User defined")}
1219         unicable_choices_default = "unicable_lnb"
1220
1221         advanced_lnb_satcruser_choices = [ ("1", "SatCR 1"), ("2", "SatCR 2"), ("3", "SatCR 3"), ("4", "SatCR 4"),
1222                                         ("5", "SatCR 5"), ("6", "SatCR 6"), ("7", "SatCR 7"), ("8", "SatCR 8")]
1223
1224         prio_list = [ ("-1", _("Auto")) ]
1225         for prio in range(65)+range(14000,14065)+range(19000,19065):
1226                 description = ""
1227                 if prio == 0:
1228                         description = _(" (disabled)")
1229                 elif 0 < prio < 65:
1230                         description = _(" (lower than any auto)")
1231                 elif 13999 < prio < 14066:
1232                         description = _(" (higher than rotor any auto)")
1233                 elif 18999 < prio < 19066:
1234                         description = _(" (higher than any auto)")
1235                 prio_list.append((str(prio), str(prio) + description))
1236
1237         advanced_lnb_csw_choices = [("none", _("None")), ("AA", _("Port A")), ("AB", _("Port B")), ("BA", _("Port C")), ("BB", _("Port D"))]
1238
1239         advanced_lnb_ucsw_choices = [("0", _("None"))] + [(str(y), "Input " + str(y)) for y in range(1, 17)]
1240
1241         diseqc_mode_choices = [
1242                 ("single", _("Single")), ("toneburst_a_b", _("Toneburst A/B")),
1243                 ("diseqc_a_b", "DiSEqC A/B"), ("diseqc_a_b_c_d", "DiSEqC A/B/C/D"),
1244                 ("positioner", _("Positioner")), ("positioner_select", _("Positioner (selecting satellites)"))]
1245
1246         positioner_mode_choices = [("usals", _("USALS")), ("manual", _("manual"))]
1247
1248         diseqc_satlist_choices = [(3600, _('automatic'), 1), (3601, _('nothing connected'), 1)] + nimmgr.satList
1249
1250         longitude_orientation_choices = [("east", _("East")), ("west", _("West"))]
1251         latitude_orientation_choices = [("north", _("North")), ("south", _("South"))]
1252         turning_speed_choices = [("fast", _("Fast")), ("slow", _("Slow")), ("fast epoch", _("Fast epoch"))]
1253
1254         advanced_satlist_choices = nimmgr.satList + [
1255                 (3601, _('All satellites 1 (USALS)'), 1), (3602, _('All satellites 2 (USALS)'), 1),
1256                 (3603, _('All satellites 3 (USALS)'), 1), (3604, _('All satellites 4 (USALS)'), 1), (3605, _('Selecting satellites 1 (USALS)'), 1), (3606, _('Selecting satellites 2 (USALS)'), 1)]
1257         advanced_lnb_choices = [("0", _("not configured"))] + [(str(y), "LNB " + str(y)) for y in range(1, 65)]
1258         advanced_voltage_choices = [("polarization", _("Polarization")), ("13V", _("13 V")), ("18V", _("18 V"))]
1259         advanced_tonemode_choices = [("band", _("Band")), ("on", _("On")), ("off", _("Off"))]
1260         advanced_lnb_toneburst_choices = [("none", _("None")), ("A", _("A")), ("B", _("B"))]
1261         advanced_lnb_allsat_diseqcmode_choices = [("1_2", _("1.2"))]
1262         advanced_lnb_diseqcmode_choices = [("none", _("None")), ("1_0", _("1.0")), ("1_1", _("1.1")), ("1_2", _("1.2"))]
1263         advanced_lnb_commandOrder1_0_choices = [("ct", "DiSEqC 1.0, toneburst"), ("tc", "toneburst, DiSEqC 1.0")]
1264         advanced_lnb_commandOrder_choices = [
1265                 ("ct", "DiSEqC 1.0, toneburst"), ("tc", "toneburst, DiSEqC 1.0"),
1266                 ("cut", "DiSEqC 1.0, DiSEqC 1.1, toneburst"), ("tcu", "toneburst, DiSEqC 1.0, DiSEqC 1.1"),
1267                 ("uct", "DiSEqC 1.1, DiSEqC 1.0, toneburst"), ("tuc", "toneburst, DiSEqC 1.1, DiSEqC 1.0")]
1268         advanced_lnb_diseqc_repeat_choices = [("none", _("None")), ("one", _("One")), ("two", _("Two")), ("three", _("Three"))]
1269         advanced_lnb_fast_turning_btime = mktime(datetime(1970, 1, 1, 7, 0).timetuple());
1270         advanced_lnb_fast_turning_etime = mktime(datetime(1970, 1, 1, 19, 0).timetuple());
1271
1272         def configLOFChanged(configElement):
1273                 if configElement.value == "unicable":
1274                         x = configElement.slot_id
1275                         lnb = configElement.lnb_id
1276                         nim = config.Nims[x]
1277                         lnbs = nim.advanced.lnb
1278                         section = lnbs[lnb]
1279                         if isinstance(section.unicable, ConfigNothing):
1280                                 if lnb == 1:
1281                                         section.unicable = ConfigSelection(unicable_choices, unicable_choices_default)
1282                                 elif lnb == 2:
1283                                         section.unicable = ConfigSelection(choices = {"unicable_matrix": _("Unicable Martix"),"unicable_user": "Unicable "+_("User defined")}, default = "unicable_matrix")
1284                                 else:
1285                                         section.unicable = ConfigSelection(choices = {"unicable_user": _("User defined")}, default = "unicable_user")
1286
1287                                 def fillUnicableConf(sectionDict, unicableproducts, vco_null_check):
1288                                         for y in unicableproducts:
1289                                                 products = unicableproducts[y].keys()
1290                                                 products.sort()
1291                                                 tmp = ConfigSubsection()
1292                                                 tmp.product = ConfigSelection(choices = products, default = products[0])
1293                                                 tmp.scr = ConfigSubDict()
1294                                                 tmp.vco = ConfigSubDict()
1295                                                 tmp.lofl = ConfigSubDict()
1296                                                 tmp.lofh = ConfigSubDict()
1297                                                 tmp.loft = ConfigSubDict()
1298                                                 tmp.positions = ConfigSubDict()
1299                                                 for z in products:
1300                                                         scrlist = []
1301                                                         vcolist = unicableproducts[y][z]
1302                                                         tmp.vco[z] = ConfigSubList()
1303                                                         for cnt in range(1,1+len(vcolist)-1):
1304                                                                 vcofreq = int(vcolist[cnt-1])
1305                                                                 if vcofreq == 0 and vco_null_check:
1306                                                                         scrlist.append(("%d" %cnt,"SCR %d " %cnt +_("not used")))
1307                                                                 else:
1308                                                                         scrlist.append(("%d" %cnt,"SCR %d" %cnt))
1309                                                                 tmp.vco[z].append(ConfigInteger(default=vcofreq, limits = (vcofreq, vcofreq)))
1310                                                                 tmp.scr[z] = ConfigSelection(choices = scrlist, default = scrlist[0][0])
1311
1312                                                                 positions = int(vcolist[len(vcolist)-1][0])
1313                                                                 tmp.positions[z] = ConfigSubList()
1314                                                                 tmp.positions[z].append(ConfigInteger(default=positions, limits = (positions, positions)))
1315
1316                                                                 lofl = vcolist[len(vcolist)-1][1]
1317                                                                 tmp.lofl[z] = ConfigSubList()
1318                                                                 tmp.lofl[z].append(ConfigInteger(default=lofl, limits = (lofl, lofl)))
1319
1320                                                                 lofh = int(vcolist[len(vcolist)-1][2])
1321                                                                 tmp.lofh[z] = ConfigSubList()
1322                                                                 tmp.lofh[z].append(ConfigInteger(default=lofh, limits = (lofh, lofh)))
1323
1324                                                                 loft = int(vcolist[len(vcolist)-1][3])
1325                                                                 tmp.loft[z] = ConfigSubList()
1326                                                                 tmp.loft[z].append(ConfigInteger(default=loft, limits = (loft, loft)))
1327                                                 sectionDict[y] = tmp
1328
1329                                 if lnb < 3:
1330                                         print "[InitNimManager] MATRIX"
1331                                         section.unicableMatrix = ConfigSubDict()
1332                                         section.unicableMatrixManufacturer = ConfigSelection(UnicableMatrixManufacturers, UnicableMatrixManufacturers[0])
1333                                         fillUnicableConf(section.unicableMatrix, unicablematrixproducts, True)
1334
1335                                 if lnb < 2:
1336                                         print "[InitNimManager] LNB"
1337                                         section.unicableLnb = ConfigSubDict()
1338                                         section.unicableLnbManufacturer = ConfigSelection(UnicableLnbManufacturers, UnicableLnbManufacturers[0])
1339                                         fillUnicableConf(section.unicableLnb, unicablelnbproducts, False)
1340
1341 #TODO satpositions for satcruser
1342                                 section.satcruser = ConfigSelection(advanced_lnb_satcruser_choices, default="1")
1343                                 tmp = ConfigSubList()
1344                                 tmp.append(ConfigInteger(default=1284, limits = (950, 2150)))
1345                                 tmp.append(ConfigInteger(default=1400, limits = (950, 2150)))
1346                                 tmp.append(ConfigInteger(default=1516, limits = (950, 2150)))
1347                                 tmp.append(ConfigInteger(default=1632, limits = (950, 2150)))
1348                                 tmp.append(ConfigInteger(default=1748, limits = (950, 2150)))
1349                                 tmp.append(ConfigInteger(default=1864, limits = (950, 2150)))
1350                                 tmp.append(ConfigInteger(default=1980, limits = (950, 2150)))
1351                                 tmp.append(ConfigInteger(default=2096, limits = (950, 2150)))
1352                                 section.satcrvcouser = tmp
1353
1354                                 nim.advanced.unicableconnected = ConfigYesNo(default=False)
1355                                 nim.advanced.unicableconnectedTo = ConfigSelection([(str(id), nimmgr.getNimDescription(id)) for id in nimmgr.getNimListOfType("DVB-S") if id != x])
1356
1357         def configDiSEqCModeChanged(configElement):
1358                 section = configElement.section
1359                 if configElement.value == "1_2" and isinstance(section.longitude, ConfigNothing):
1360                         section.longitude = ConfigFloat(default = [5,100], limits = [(0,359),(0,999)])
1361                         section.longitudeOrientation = ConfigSelection(longitude_orientation_choices, "east")
1362                         section.latitude = ConfigFloat(default = [50,767], limits = [(0,359),(0,999)])
1363                         section.latitudeOrientation = ConfigSelection(latitude_orientation_choices, "north")
1364                         section.tuningstepsize = ConfigFloat(default = [0,360], limits = [(0,9),(0,999)])
1365                         section.rotorPositions = ConfigInteger(default = 99, limits = [1,999])
1366                         section.turningspeedH = ConfigFloat(default = [2,3], limits = [(0,9),(0,9)])
1367                         section.turningspeedV = ConfigFloat(default = [1,7], limits = [(0,9),(0,9)])
1368                         section.powerMeasurement = ConfigYesNo(default=True)
1369                         section.powerThreshold = ConfigInteger(default=15, limits=(0, 100))
1370                         section.turningSpeed = ConfigSelection(turning_speed_choices, "fast")
1371                         section.fastTurningBegin = ConfigDateTime(default=advanced_lnb_fast_turning_btime, formatstring = _("%H:%M"), increment = 600)
1372                         section.fastTurningEnd = ConfigDateTime(default=advanced_lnb_fast_turning_etime, formatstring = _("%H:%M"), increment = 600)
1373
1374         def configLNBChanged(configElement):
1375                 x = configElement.slot_id
1376                 nim = config.Nims[x]
1377                 if isinstance(configElement.value, tuple):
1378                         lnb = int(configElement.value[0])
1379                 else:
1380                         lnb = int(configElement.value)
1381                 lnbs = nim.advanced.lnb
1382                 if lnb and lnb not in lnbs:
1383                         section = lnbs[lnb] = ConfigSubsection()
1384                         section.lofl = ConfigInteger(default=9750, limits = (0, 99999))
1385                         section.lofh = ConfigInteger(default=10600, limits = (0, 99999))
1386                         section.threshold = ConfigInteger(default=11700, limits = (0, 99999))
1387                         section.increased_voltage = ConfigYesNo(False)
1388                         section.toneburst = ConfigSelection(advanced_lnb_toneburst_choices, "none")
1389                         section.longitude = ConfigNothing()
1390                         if lnb > 64:
1391                                 tmp = ConfigSelection(advanced_lnb_allsat_diseqcmode_choices, "1_2")
1392                                 tmp.section = section
1393                                 configDiSEqCModeChanged(tmp)
1394                         else:
1395                                 tmp = ConfigSelection(advanced_lnb_diseqcmode_choices, "none")
1396                                 tmp.section = section
1397                                 tmp.addNotifier(configDiSEqCModeChanged)
1398                         section.diseqcMode = tmp
1399                         section.commitedDiseqcCommand = ConfigSelection(advanced_lnb_csw_choices)
1400                         section.fastDiseqc = ConfigYesNo(False)
1401                         section.sequenceRepeat = ConfigYesNo(False)
1402                         section.commandOrder1_0 = ConfigSelection(advanced_lnb_commandOrder1_0_choices, "ct")
1403                         section.commandOrder = ConfigSelection(advanced_lnb_commandOrder_choices, "ct")
1404                         section.uncommittedDiseqcCommand = ConfigSelection(advanced_lnb_ucsw_choices)
1405                         section.diseqcRepeats = ConfigSelection(advanced_lnb_diseqc_repeat_choices, "none")
1406                         section.prio = ConfigSelection(prio_list, "-1")
1407                         section.unicable = ConfigNothing()
1408                         tmp = ConfigSelection(lnb_choices, lnb_choices_default)
1409                         tmp.slot_id = x
1410                         tmp.lnb_id = lnb
1411                         tmp.addNotifier(configLOFChanged, initial_call = False)
1412                         section.lof = tmp
1413
1414         def configModeChanged(configMode):
1415                 slot_id = configMode.slot_id
1416                 nim = config.Nims[slot_id]
1417                 if configMode.value == "advanced" and isinstance(nim.advanced, ConfigNothing):
1418                         # advanced config:
1419                         nim.advanced = ConfigSubsection()
1420                         nim.advanced.sat = ConfigSubDict()
1421                         nim.advanced.sats = getConfigSatlist(192, advanced_satlist_choices)
1422                         nim.advanced.lnb = ConfigSubDict()
1423                         nim.advanced.lnb[0] = ConfigNothing()
1424                         for x in nimmgr.satList:
1425                                 tmp = ConfigSubsection()
1426                                 tmp.voltage = ConfigSelection(advanced_voltage_choices, "polarization")
1427                                 tmp.tonemode = ConfigSelection(advanced_tonemode_choices, "band")
1428                                 tmp.usals = ConfigYesNo(True)
1429                                 tmp.rotorposition = ConfigInteger(default=1, limits=(1, 255))
1430                                 lnb = ConfigSelection(advanced_lnb_choices, "0")
1431                                 lnb.slot_id = slot_id
1432                                 lnb.addNotifier(configLNBChanged, initial_call = False)
1433                                 tmp.lnb = lnb
1434                                 nim.advanced.sat[x[0]] = tmp
1435                         for x in range(3601, 3607):
1436                                 tmp = ConfigSubsection()
1437                                 tmp.voltage = ConfigSelection(advanced_voltage_choices, "polarization")
1438                                 tmp.tonemode = ConfigSelection(advanced_tonemode_choices, "band")
1439                                 tmp.usals = ConfigYesNo(default=True)
1440                                 tmp.userSatellitesList = ConfigText('[]')
1441                                 tmp.rotorposition = ConfigInteger(default=1, limits=(1, 255))
1442                                 lnbnum = 65+x-3601
1443                                 lnb = ConfigSelection([("0", _("not configured")), (str(lnbnum), "LNB %d"%(lnbnum))], "0")
1444                                 lnb.slot_id = slot_id
1445                                 lnb.addNotifier(configLNBChanged, initial_call = False)
1446                                 tmp.lnb = lnb
1447                                 nim.advanced.sat[x] = tmp
1448
1449         def toneAmplitudeChanged(configElement):
1450                 fe_id = configElement.fe_id
1451                 slot_id = configElement.slot_id
1452                 if nimmgr.nim_slots[slot_id].description == 'Alps BSBE2':
1453                         open("/proc/stb/frontend/%d/tone_amplitude" %(fe_id), "w").write(configElement.value)
1454
1455         def createSatConfig(nim, x, empty_slots):
1456                 try:
1457                         nim.toneAmplitude
1458                 except:
1459                         nim.toneAmplitude = ConfigSelection([("11", "340mV"), ("10", "360mV"), ("9", "600mV"), ("8", "700mV"), ("7", "800mV"), ("6", "900mV"), ("5", "1100mV")], "7")
1460                         nim.toneAmplitude.fe_id = x - empty_slots
1461                         nim.toneAmplitude.slot_id = x
1462                         nim.toneAmplitude.addNotifier(toneAmplitudeChanged)
1463                         nim.diseqc13V = ConfigYesNo(False)
1464                         nim.diseqcMode = ConfigSelection(diseqc_mode_choices, "diseqc_a_b")
1465                         nim.connectedTo = ConfigSelection([(str(id), nimmgr.getNimDescription(id)) for id in nimmgr.getNimListOfType("DVB-S") if id != x])
1466                         nim.simpleSingleSendDiSEqC = ConfigYesNo(False)
1467                         nim.simpleDiSEqCSetVoltageTone = ConfigYesNo(True)
1468                         nim.simpleDiSEqCOnlyOnSatChange = ConfigYesNo(False)
1469                         nim.simpleDiSEqCSetCircularLNB = ConfigYesNo(True)
1470                         nim.diseqcA = ConfigSatlist(list = diseqc_satlist_choices)
1471                         nim.diseqcB = ConfigSatlist(list = diseqc_satlist_choices)
1472                         nim.diseqcC = ConfigSatlist(list = diseqc_satlist_choices)
1473                         nim.diseqcD = ConfigSatlist(list = diseqc_satlist_choices)
1474                         nim.positionerMode = ConfigSelection(positioner_mode_choices, "usals")
1475                         nim.userSatellitesList = ConfigText('[]')
1476                         nim.pressOKtoList = ConfigNothing()
1477                         nim.longitude = ConfigFloat(default=[5,100], limits=[(0,359),(0,999)])
1478                         nim.longitudeOrientation = ConfigSelection(longitude_orientation_choices, "east")
1479                         nim.latitude = ConfigFloat(default=[50,767], limits=[(0,359),(0,999)])
1480                         nim.latitudeOrientation = ConfigSelection(latitude_orientation_choices, "north")
1481                         nim.tuningstepsize = ConfigFloat(default = [0,360], limits = [(0,9),(0,999)])
1482                         nim.rotorPositions = ConfigInteger(default = 99, limits = [1,999])
1483                         nim.turningspeedH = ConfigFloat(default = [2,3], limits = [(0,9),(0,9)])
1484                         nim.turningspeedV = ConfigFloat(default = [1,7], limits = [(0,9),(0,9)])
1485                         nim.powerMeasurement = ConfigYesNo(True)
1486                         nim.powerThreshold = ConfigInteger(default=hw.get_device_name() == "dm8000" and 15 or 50, limits=(0, 100))
1487                         nim.turningSpeed = ConfigSelection(turning_speed_choices, "fast")
1488                         btime = datetime(1970, 1, 1, 7, 0);
1489                         nim.fastTurningBegin = ConfigDateTime(default = mktime(btime.timetuple()), formatstring = _("%H:%M"), increment = 900)
1490                         etime = datetime(1970, 1, 1, 19, 0);
1491                         nim.fastTurningEnd = ConfigDateTime(default = mktime(etime.timetuple()), formatstring = _("%H:%M"), increment = 900)
1492
1493         def createCableConfig(nim, x):
1494                 try:
1495                         nim.cable
1496                 except:
1497                         list = [ ]
1498                         n = 0
1499                         for x in nimmgr.cablesList:
1500                                 list.append((str(n), x[0]))
1501                                 n += 1
1502                         nim.cable = ConfigSubsection()
1503                         nim.cable.scan_networkid = ConfigInteger(default = 0, limits = (0, 99999))
1504                         possible_scan_types = [("bands", _("Frequency bands")), ("steps", _("Frequency steps"))]
1505                         if n:
1506                                 possible_scan_types.append(("provider", _("Provider")))
1507                                 nim.cable.scan_provider = ConfigSelection(default = "0", choices = list)
1508                         nim.cable.scan_type = ConfigSelection(default = "bands", choices = possible_scan_types)
1509                         nim.cable.scan_band_EU_VHF_I = ConfigYesNo(default = True)
1510                         nim.cable.scan_band_EU_MID = ConfigYesNo(default = True)
1511                         nim.cable.scan_band_EU_VHF_III = ConfigYesNo(default = True)
1512                         nim.cable.scan_band_EU_UHF_IV = ConfigYesNo(default = True)
1513                         nim.cable.scan_band_EU_UHF_V = ConfigYesNo(default = True)
1514                         nim.cable.scan_band_EU_SUPER = ConfigYesNo(default = True)
1515                         nim.cable.scan_band_EU_HYPER = ConfigYesNo(default = True)
1516                         nim.cable.scan_band_US_LOW = ConfigYesNo(default = False)
1517                         nim.cable.scan_band_US_MID = ConfigYesNo(default = False)
1518                         nim.cable.scan_band_US_HIGH = ConfigYesNo(default = False)
1519                         nim.cable.scan_band_US_SUPER = ConfigYesNo(default = False)
1520                         nim.cable.scan_band_US_HYPER = ConfigYesNo(default = False)
1521                         nim.cable.scan_frequency_steps = ConfigInteger(default = 1000, limits = (1000, 10000))
1522                         nim.cable.scan_mod_qam16 = ConfigYesNo(default = False)
1523                         nim.cable.scan_mod_qam32 = ConfigYesNo(default = False)
1524                         nim.cable.scan_mod_qam64 = ConfigYesNo(default = True)
1525                         nim.cable.scan_mod_qam128 = ConfigYesNo(default = False)
1526                         nim.cable.scan_mod_qam256 = ConfigYesNo(default = True)
1527                         nim.cable.scan_sr_6900 = ConfigYesNo(default = True)
1528                         nim.cable.scan_sr_6875 = ConfigYesNo(default = True)
1529                         nim.cable.scan_sr_ext1 = ConfigInteger(default = 0, limits = (0, 7230))
1530                         nim.cable.scan_sr_ext2 = ConfigInteger(default = 0, limits = (0, 7230))
1531
1532         def createTerrestrialConfig(nim, x):
1533                 try:
1534                         nim.terrestrial
1535                 except:
1536                         list = []
1537                         n = 0
1538                         for x in nimmgr.terrestrialsList:
1539                                 list.append((str(n), x[0]))
1540                                 n += 1
1541                         nim.terrestrial = ConfigSelection(choices = list)
1542                         nim.terrestrial_5V = ConfigOnOff()
1543
1544         empty_slots = 0
1545         for slot in nimmgr.nim_slots:
1546                 x = slot.slot
1547                 nim = config.Nims[x]
1548
1549                 if slot.isCompatible("DVB-S"):
1550                         createSatConfig(nim, x, empty_slots)
1551                         config_mode_choices = [("nothing", _("nothing connected")),
1552                                 ("simple", _("simple")), ("advanced", _("advanced"))]
1553                         if len(nimmgr.getNimListOfType(slot.type, exception = x)) > 0:
1554                                 config_mode_choices.append(("equal", _("equal to")))
1555                                 config_mode_choices.append(("satposdepends", _("second cable of motorized LNB")))
1556                         if len(nimmgr.canConnectTo(x)) > 0:
1557                                 config_mode_choices.append(("loopthrough", _("loopthrough to")))
1558                         nim.advanced = ConfigNothing()
1559                         tmp = ConfigSelection(config_mode_choices, "simple")
1560                         tmp.slot_id = x
1561                         tmp.addNotifier(configModeChanged, initial_call = False)
1562                         nim.configMode = tmp
1563                 elif slot.isCompatible("DVB-C"):
1564                         nim.configMode = ConfigSelection(
1565                                 choices = {
1566                                         "enabled": _("enabled"),
1567                                         "nothing": _("nothing connected"),
1568                                         },
1569                                 default = "enabled")
1570                         createCableConfig(nim, x)
1571                 elif slot.isCompatible("DVB-T"):
1572                         nim.configMode = ConfigSelection(
1573                                 choices = {
1574                                         "enabled": _("enabled"),
1575                                         "nothing": _("nothing connected"),
1576                                         },
1577                                 default = "enabled")
1578                         createTerrestrialConfig(nim, x)
1579                 else:
1580                         empty_slots += 1
1581                         nim.configMode = ConfigSelection(choices = { "nothing": _("disabled") }, default="nothing");
1582                         if slot.type is not None:
1583                                 print "[InitNimManager] pls add support for this frontend type!", slot.type
1584
1585         nimmgr.sec = SecConfigure(nimmgr)
1586
1587         def tunerTypeChanged(nimmgr, configElement):
1588                 fe_id = configElement.fe_id
1589                 eDVBResourceManager.getInstance().setFrontendType(nimmgr.nim_slots[fe_id].frontend_id, nimmgr.nim_slots[fe_id].getType())
1590                 try:
1591                         cur_type = int(open("/proc/stb/frontend/%d/mode" % (fe_id), "r").read())
1592                         if cur_type != int(configElement.value):
1593                                 print "tunerTypeChanged feid %d from %d to mode %d" % (fe_id, cur_type, int(configElement.value))
1594
1595                                 try:
1596                                         oldvalue = open("/sys/module/dvb_core/parameters/dvb_shutdown_timeout", "r").readline()
1597                                         open("/sys/module/dvb_core/parameters/dvb_shutdown_timeout", "w").write("0")
1598                                 except:
1599                                         print "[InitNimManager] no /sys/module/dvb_core/parameters/dvb_shutdown_timeout available"
1600
1601                                 frontend = eDVBResourceManager.getInstance().allocateRawChannel(fe_id).getFrontend()
1602                                 frontend.closeFrontend()
1603                                 open("/proc/stb/frontend/%d/mode" % (fe_id), "w").write(configElement.value)
1604                                 frontend.reopenFrontend()
1605                                 try:
1606                                         open("/sys/module/dvb_core/parameters/dvb_shutdown_timeout", "w").write(oldvalue)
1607                                 except:
1608                                         print "[InitNimManager] no /sys/module/dvb_core/parameters/dvb_shutdown_timeout available"
1609                                 nimmgr.enumerateNIMs()
1610                         else:
1611                                 print "[InitNimManager] tuner type is already already %d" %cur_type
1612                 except:
1613                         pass
1614
1615         empty_slots = 0
1616         for slot in nimmgr.nim_slots:
1617                 x = slot.slot
1618                 nim = config.Nims[x]
1619                 addMultiType = False
1620                 try:
1621                         nim.multiType
1622                 except:
1623                         addMultiType = True
1624                 if slot.isMultiType() and addMultiType:
1625                         typeList = []
1626                         for id in slot.getMultiTypeList().keys():
1627                                 type = slot.getMultiTypeList()[id]
1628                                 typeList.append((id, type))
1629                         nim.multiType = ConfigSelection(typeList, "0")
1630
1631                         nim.multiType.fe_id = x - empty_slots
1632                         nim.multiType.addNotifier(boundFunction(tunerTypeChanged, nimmgr))
1633
1634         empty_slots = 0
1635         for slot in nimmgr.nim_slots:
1636                 x = slot.slot
1637                 nim = config.Nims[x]
1638                 empty = True
1639
1640                 if slot.canBeCompatible("DVB-S"):
1641                         createSatConfig(nim, x, empty_slots)
1642                         empty = False
1643                 if slot.canBeCompatible("DVB-C"):
1644                         createCableConfig(nim, x)
1645                         empty = False
1646                 if slot.canBeCompatible("DVB-T"):
1647                         createTerrestrialConfig(nim, x)
1648                         empty = False
1649                 if empty:
1650                         empty_slots += 1
1651
1652 nimmanager = NimManager()