Support turbo2.
[vuplus_dvbapp] / lib / python / Screens / Ci.py
1 from Screen import Screen
2 from Components.ActionMap import ActionMap
3 from Components.ActionMap import NumberActionMap
4 from Components.Label import Label
5
6 from Components.config import config, ConfigSubsection, ConfigSelection, ConfigSubList, getConfigListEntry, KEY_LEFT, KEY_RIGHT, KEY_0, ConfigNothing, ConfigPIN, ConfigYesNo
7 from Components.ConfigList import ConfigList
8
9 from Components.SystemInfo import SystemInfo
10 from Tools.Directories import fileExists
11
12 from enigma import eTimer, eDVBCI_UI, eDVBCIInterfaces
13
14 def setCIBitrate(configElement):
15         eDVBCI_UI.getInstance().setClockRate(configElement.slotid, eDVBCI_UI.rateHigh if configElement.value else eDVBCI_UI.rateNormal)
16
17 def setRelevantPidsRouting(configElement):
18         open(SystemInfo["CI%dRelevantPidsRoutingSupport" % configElement.slotid], "w").write("yes" if configElement.value else "no")
19
20 def setdvbCiDelay(configElement):
21         open(SystemInfo["CommonInterfaceCIDelay"], "w").write(configElement.value)
22         configElement.save()
23
24 def InitCiConfig():
25         config.ci = ConfigSubList()
26         config.cimisc = ConfigSubsection()
27         if SystemInfo["CommonInterface"]:
28                 for slot in range(SystemInfo["CommonInterface"]):
29                         config.ci.append(ConfigSubsection())
30                         config.ci[slot].canDescrambleMultipleServices = ConfigSelection(choices = [("auto", _("Auto")), ("no", _("No")), ("yes", _("Yes"))], default = "auto")
31                         if SystemInfo["CI%dSupportsHighBitrates" % slot]:
32                                 config.ci[slot].canHandleHighBitrates = ConfigYesNo(default = False)
33                                 config.ci[slot].canHandleHighBitrates.slotid = slot
34                                 config.ci[slot].canHandleHighBitrates.addNotifier(setCIBitrate)
35
36                         if SystemInfo["CI%dRelevantPidsRoutingSupport" % slot]:
37                                 config.ci[slot].relevantPidsRouting = ConfigYesNo(default = False)
38                                 config.ci[slot].relevantPidsRouting.slotid = slot
39                                 config.ci[slot].relevantPidsRouting.addNotifier(setRelevantPidsRouting)
40
41                 if SystemInfo["CommonInterfaceCIDelay"]:
42                         config.cimisc.dvbCiDelay = ConfigSelection(default = "256", choices = [("16"), ("32"), ("64"), ("128"), ("256")])
43                         config.cimisc.dvbCiDelay.addNotifier(setdvbCiDelay)
44                         
45 class MMIDialog(Screen):
46         def __init__(self, session, slotid, action, handler = eDVBCI_UI.getInstance(), wait_text = _("wait for ci...") ):
47                 Screen.__init__(self, session)
48
49                 print "MMIDialog with action" + str(action)
50
51                 self.mmiclosed = False
52                 self.tag = None
53                 self.slotid = slotid
54
55                 self.timer = eTimer()
56                 self.timer.callback.append(self.keyCancel)
57
58                 #else the skins fails
59                 self["title"] = Label("")
60                 self["subtitle"] = Label("")
61                 self["bottom"] = Label("")
62                 self["entries"] = ConfigList([ ])
63
64                 self["actions"] = NumberActionMap(["SetupActions"],
65                         {
66                                 "ok": self.okbuttonClick,
67                                 "cancel": self.keyCancel,
68                                 #for PIN
69                                 "left": self.keyLeft,
70                                 "right": self.keyRight,
71                                 "1": self.keyNumberGlobal,
72                                 "2": self.keyNumberGlobal,
73                                 "3": self.keyNumberGlobal,
74                                 "4": self.keyNumberGlobal,
75                                 "5": self.keyNumberGlobal,
76                                 "6": self.keyNumberGlobal,
77                                 "7": self.keyNumberGlobal,
78                                 "8": self.keyNumberGlobal,
79                                 "9": self.keyNumberGlobal,
80                                 "0": self.keyNumberGlobal
81                         }, -1)
82
83                 self.action = action
84
85                 self.handler = handler
86                 self.wait_text = wait_text
87
88                 if action == 2:         #start MMI
89                         handler.startMMI(self.slotid)
90                         self.showWait()
91                 elif action == 3:               #mmi already there (called from infobar)
92                         self.showScreen()
93
94         def addEntry(self, list, entry):
95                 if entry[0] == "TEXT":          #handle every item (text / pin only?)
96                         list.append( (entry[1], ConfigNothing(), entry[2]) )
97                 if entry[0] == "PIN":
98                         pinlength = entry[1]
99                         if entry[3] == 1:
100                                 # masked pins:
101                                 x = ConfigPIN(0, len = pinlength, censor = "*")
102                         else:
103                                 # unmasked pins:
104                                 x = ConfigPIN(0, len = pinlength)
105                         self["subtitle"].setText(entry[2])
106                         list.append( getConfigListEntry("", x) )
107                         self["bottom"].setText(_("please press OK when ready"))
108
109         def okbuttonClick(self):
110                 self.timer.stop()
111                 if not self.tag:
112                         return
113                 if self.tag == "WAIT":
114                         print "do nothing - wait"
115                 elif self.tag == "MENU":
116                         print "answer MENU"
117                         cur = self["entries"].getCurrent()
118                         if cur:
119                                 self.handler.answerMenu(self.slotid, cur[2])
120                         else:
121                                 self.handler.answerMenu(self.slotid, 0)
122                         self.showWait()
123                 elif self.tag == "LIST":
124                         print "answer LIST"
125                         self.handler.answerMenu(self.slotid, 0)
126                         self.showWait()
127                 elif self.tag == "ENQ":
128                         cur = self["entries"].getCurrent()
129                         answer = str(cur[1].value)
130                         length = len(answer)
131                         while length < cur[1].getLength():
132                                 answer = '0'+answer
133                                 length+=1
134                         self.handler.answerEnq(self.slotid, answer)
135                         self.showWait()
136
137         def closeMmi(self):
138                 self.timer.stop()
139                 self.close(self.slotid)
140
141         def keyCancel(self):
142                 self.timer.stop()
143                 if not self.tag or self.mmiclosed:
144                         self.closeMmi()
145                 elif self.tag == "WAIT":
146                         self.handler.stopMMI(self.slotid)
147                         self.closeMmi()
148                 elif self.tag in ( "MENU", "LIST" ):
149                         print "cancel list"
150                         self.handler.answerMenu(self.slotid, 0)
151                         self.showWait()
152                 elif self.tag == "ENQ":
153                         print "cancel enq"
154                         self.handler.cancelEnq(self.slotid)
155                         self.showWait()
156                 else:
157                         print "give cancel action to ci"
158
159         def keyConfigEntry(self, key):
160                 self.timer.stop()
161                 try:
162                         self["entries"].handleKey(key)
163                 except:
164                         pass
165
166         def keyNumberGlobal(self, number):
167                 self.timer.stop()
168                 self.keyConfigEntry(KEY_0 + number)
169
170         def keyLeft(self):
171                 self.timer.stop()
172                 self.keyConfigEntry(KEY_LEFT)
173
174         def keyRight(self):
175                 self.timer.stop()
176                 self.keyConfigEntry(KEY_RIGHT)
177
178         def updateList(self, list):
179                 List = self["entries"]
180                 try:
181                         List.instance.moveSelectionTo(0)
182                 except:
183                         pass
184                 List.l.setList(list)
185
186         def showWait(self):
187                 self.tag = "WAIT"
188                 self["title"].setText("")
189                 self["subtitle"].setText("")
190                 self["bottom"].setText("")
191                 list = [ ]
192                 list.append( (self.wait_text, ConfigNothing()) )
193                 self.updateList(list)
194
195         def showScreen(self):
196                 screen = self.handler.getMMIScreen(self.slotid)
197
198                 list = [ ]
199
200                 self.timer.stop()
201                 if len(screen) > 0 and screen[0][0] == "CLOSE":
202                         timeout = screen[0][1]
203                         self.mmiclosed = True
204                         if timeout > 0:
205                                 self.timer.start(timeout*1000, True)
206                         else:
207                                 self.keyCancel()
208                 else:
209                         self.mmiclosed = False
210                         self.tag = screen[0][0]
211                         for entry in screen:
212                                 if entry[0] == "PIN":
213                                         self.addEntry(list, entry)
214                                 else:
215                                         if entry[0] == "TITLE":
216                                                 self["title"].setText(entry[1])
217                                         elif entry[0] == "SUBTITLE":
218                                                 self["subtitle"].setText(entry[1])
219                                         elif entry[0] == "BOTTOM":
220                                                 self["bottom"].setText(entry[1])
221                                         elif entry[0] == "TEXT":
222                                                 self.addEntry(list, entry)
223                         self.updateList(list)
224
225         def ciStateChanged(self):
226                 do_close = False
227                 if self.action == 0:                    #reset
228                         do_close = True
229                 if self.action == 1:                    #init
230                         do_close = True
231
232                 #module still there ?
233                 if self.handler.getState(self.slotid) != 2:
234                         do_close = True
235
236                 #mmi session still active ?
237                 if self.handler.getMMIState(self.slotid) != 1:
238                         do_close = True
239
240                 if do_close:
241                         self.closeMmi()
242                 elif self.action > 1 and self.handler.availableMMI(self.slotid) == 1:
243                         self.showScreen()
244
245                 #FIXME: check for mmi-session closed
246
247 class CiMessageHandler:
248         def __init__(self):
249                 self.session = None
250                 self.ci = { }
251                 self.dlgs = { }
252                 eDVBCI_UI.getInstance().ciStateChanged.get().append(self.ciStateChanged)
253
254         def setSession(self, session):
255                 self.session = session
256
257         def ciStateChanged(self, slot):
258                 if slot in self.ci:
259                         self.ci[slot](slot)
260                 else:
261                         if slot in self.dlgs:
262                                 self.dlgs[slot].ciStateChanged()
263                         elif eDVBCI_UI.getInstance().availableMMI(slot) == 1:
264                                 if self.session:
265                                         self.dlgs[slot] = self.session.openWithCallback(self.dlgClosed, MMIDialog, slot, 3)
266
267         def dlgClosed(self, slot):
268                 if slot in self.dlgs:
269                         del self.dlgs[slot]
270
271         def registerCIMessageHandler(self, slot, func):
272                 self.unregisterCIMessageHandler(slot)
273                 self.ci[slot] = func
274
275         def unregisterCIMessageHandler(self, slot):
276                 if slot in self.ci:
277                         del self.ci[slot]
278
279 CiHandler = CiMessageHandler()
280
281 class CiSelection(Screen):
282         def __init__(self, session):
283                 Screen.__init__(self, session)
284                 self["actions"] = ActionMap(["OkCancelActions", "CiSelectionActions"],
285                         {
286                                 "left": self.keyLeft,
287                                 "right": self.keyLeft,
288                                 "ok": self.okbuttonClick,
289                                 "cancel": self.cancel
290                         },-1)
291
292                 self.dlg = None
293                 self.state = { }
294                 self.slots = []
295                 self.HighBitrateEntry = {}
296                 self.RelevantPidsRoutingEntry = {}
297
298                 self.entryData = []
299                 self.DVBCiDelayEntry = None
300
301                 self.list = [ ]
302                 self["entries"] = ConfigList(self.list)
303                 self["entries"].list = self.list
304                 self["entries"].l.setList(self.list)
305                 self["text"] = Label(_("Slot %d")%(1))
306                 self.onLayoutFinish.append(self.initialUpdate)
307
308         def initialUpdate(self):
309                 for slot in range(SystemInfo["CommonInterface"]):
310                         state = eDVBCI_UI.getInstance().getState(slot)
311                         if state != -1:
312                                 self.slots.append(slot)
313                                 self.state[slot] = state
314                                 self.createEntries(slot)
315                                 CiHandler.registerCIMessageHandler(slot, self.ciStateChanged)
316
317                 self.slots.sort()
318                 self.updateEntries()
319                 if self.slots:
320                         self["text"].setText(_("Slot %d")% (int(self.slots[0])+1))
321
322         def selectionChanged(self):
323                 entryData = self.entryData[self["entries"].getCurrentIndex()]
324                 self["text"].setText(_("Slot %d")%(entryData[1] + 1))
325
326         def keyConfigEntry(self, key):
327                 current = self["entries"].getCurrent()
328                 try:
329                         self["entries"].handleKey(key)
330                         current[1].save()
331                 except:
332                         pass
333
334         def keyLeft(self):
335                 self.keyConfigEntry(KEY_LEFT)
336
337         def keyRight(self):
338                 self.keyConfigEntry(KEY_RIGHT)
339
340         def createEntries(self, slot):
341                 if SystemInfo["CI%dSupportsHighBitrates" % slot]:
342                         self.HighBitrateEntry[slot] = getConfigListEntry(_("High bitrate support"), config.ci[slot].canHandleHighBitrates)
343                 if SystemInfo["CI%dRelevantPidsRoutingSupport" % slot]:
344                         self.RelevantPidsRoutingEntry[slot] = getConfigListEntry(_("PID Filtering"), config.ci[slot].relevantPidsRouting)
345                 if SystemInfo["CommonInterfaceCIDelay"] and self.DVBCiDelayEntry is None:
346                         self.DVBCiDelayEntry = getConfigListEntry(_("DVB CI Delay"), config.cimisc.dvbCiDelay)
347
348         def addToList(self, data, action, slotid):
349                 self.list.append(data)
350                 self.entryData.append((action, slotid))
351
352         def updateEntries(self):
353                 self.list = []
354                 self.entryData = []
355
356                 for slot in self.slots:
357                         self.addToList((_("Reset"), ConfigNothing()), 0, slot)
358                         self.addToList((_("Init"), ConfigNothing()), 1, slot)
359
360                         if self.state[slot] == 0:                       #no module
361                                 self.addToList((_("no module found"), ConfigNothing()), 2, slot)
362                         elif self.state[slot] == 1:             #module in init
363                                 self.addToList((_("init module"), ConfigNothing()), 2, slot)
364                         elif self.state[slot] == 2:             #module ready
365                                 #get appname
366                                 appname = eDVBCI_UI.getInstance().getAppName(slot)
367                                 self.addToList((appname, ConfigNothing()), 2, slot)
368
369                         self.addToList(getConfigListEntry(_("Multiple service support"), config.ci[slot].canDescrambleMultipleServices), -1, slot)
370
371                         if SystemInfo["CI%dSupportsHighBitrates" % slot]:
372                                 self.addToList(self.HighBitrateEntry[slot], -1, slot)
373                         if SystemInfo["CI%dRelevantPidsRoutingSupport" % slot]:
374                                 self.addToList(self.RelevantPidsRoutingEntry[slot], -1, slot)
375                         if SystemInfo["CommonInterfaceCIDelay"]:
376                                 self.addToList(self.DVBCiDelayEntry, -1, slot)
377
378                 self["entries"].list = self.list
379                 self["entries"].l.setList(self.list)
380                 if self.selectionChanged not in self["entries"].onSelectionChanged:
381                         self["entries"].onSelectionChanged.append(self.selectionChanged)
382
383         def ciStateChanged(self, slot):
384                 if self.dlg:
385                         self.dlg.ciStateChanged()
386                 else:
387                         state = eDVBCI_UI.getInstance().getState(slot)
388                         if self.state[slot] != state:
389                                 #print "something happens"
390                                 self.state[slot] = state
391                                 self.updateEntries()
392
393         def dlgClosed(self, slot):
394                 self.dlg = None
395
396         def okbuttonClick(self):
397                 cur = self["entries"].getCurrent()
398                 if cur:
399                         idx = self["entries"].getCurrentIndex()
400                         entryData = self.entryData[idx]
401                         action = entryData[0]
402                         slot = entryData[1]
403                         if action == 0:         #reset
404                                 eDVBCI_UI.getInstance().setReset(slot)
405                         elif action == 1:               #init
406                                 eDVBCI_UI.getInstance().setInit(slot)
407                         elif action == 2 and self.state[slot] == 2:
408                                 self.dlg = self.session.openWithCallback(self.dlgClosed, MMIDialog, slot, action)
409
410         def cancel(self):
411                 for slot in range(SystemInfo["CommonInterface"]):
412                         state = eDVBCI_UI.getInstance().getState(slot)
413                         if state != -1:
414                                 CiHandler.unregisterCIMessageHandler(slot)
415                 self.close()