[TeleText] added colored buttons to menu
[enigma2-plugins.git] / teletext / src / plugin.py
1 from __init__ import _, _debug , _log
2
3 from enigma import iServiceInformation, iPlayableService, eSocketNotifier, getDesktop, ePoint, eSize
4
5 from Screens.HelpMenu import HelpMenu
6 from Screens.MessageBox import MessageBox
7 from Screens.Screen import Screen
8 from Components.ActionMap import ActionMap, NumberActionMap
9 from Components.ConfigList import ConfigListScreen
10 from Components.Label import Label
11 from Components.Pixmap import Pixmap
12 from Components.ServiceEventTracker import ServiceEventTracker
13 from Components.Sources.StaticText import StaticText
14 from Components.config import config, configfile, getConfigListEntry, ConfigSubsection, ConfigEnableDisable, ConfigSlider, ConfigSelection, ConfigSequence
15 from GlobalActions import globalActionMap
16 from Plugins.Plugin import PluginDescriptor
17 from Tools.Directories import resolveFilename, SCOPE_PLUGINS
18
19 import array
20 import socket
21 import struct
22
23 from os import unlink
24 from select import POLLIN, POLLPRI, POLLHUP, POLLERR
25
26 from enigma import Teletext as TeletextInterface
27
28 CMD_CTL_CACHE=1
29 CMD_SHOW_PAGE=2
30 CMD_PAGE_NEXT=3
31 CMD_PAGE_PREV=4
32 CMD_SUBP_NEXT=5
33 CMD_SUBP_PREV=6
34 CMD_COLKEY_RD=7
35 CMD_COLKEY_GN=8
36 CMD_COLKEY_YE=9
37 CMD_COLKEY_BL=10
38 CMD_CATCHPAGE=11
39 CMD_CONCEALED=12
40 CMD_SET_BRIGH=13
41 CMD_SET_CONTR=14
42 CMD_RQ_UPDATE=15
43 CMD_RZAP_PAGE=16
44 CMD_OPAQUE=17
45 CMD_TRANSPARENCY=18
46 CMD_FLOF=19
47 CMD_PAGEINPUT=20
48 CMD_EDGE_CUT=21
49 CMD_TEXTLEVEL=22
50 CMD_REGION=23
51 CMD_CLOSE_DMN=99
52
53 SPLIT_MODE_PAT = "pat"
54 SPLIT_MODE_TAP = "tap"
55 SPLIT_MODE_TIP = "tip"
56 splittingModeList = [ (SPLIT_MODE_PAT, _("picture and teletext")), (SPLIT_MODE_TAP, _("teletext and picture")), (SPLIT_MODE_TIP, _("teletext in picture")) ]
57 textlevelModeList = [ ("0", "1.0"), ("1", "1.5"), ("2", "2.5"), ("3", "3.5") ]
58 regionList = [ ("0", _("Western and Central Europe")), ("8", _("Eastern Europe")), ("16", _("Western Europe and Turkey")), ("24", _("Central and Southeast Europe")), ("32", _("Cyrillic")), ("48", _("Turkish / Greek")), ("64", _("Arabic")), ("80", _("Hebrew / Arabic")) ]
59
60 HELP_TEXT_POS          = _("Enter values (left, top, right, bottom) or press TEXT to move and resize the teletext graphically.")
61 HELP_TEXT_TIP_POS      = _("Enter values (left, top, right, bottom) or press TEXT to move and resize the teletext graphically.")
62 HELP_TEXT_SPLITTING    = _("Select splitting mode.")
63 HELP_TEXT_BRIGHTNESS   = _("Select brightness.")
64 HELP_TEXT_CONTRAST     = _("Select contrast.")
65 HELP_TEXT_TRANSPARENCY = _("Select transparency.")
66 HELP_TEXT_EDGE_CUT     = _("Display first and last row.")
67 HELP_TEXT_MESSAGES     = _("Show message if no teletext available or exit silently.")
68 HELP_TEXT_DEBUG        = _("Print debug messages to /tmp/dbttcp.log.")
69 HELP_TEXT_TEXTLEVEL    = _("Select teletext version to use.")
70 HELP_TEXT_REGION       = _("Select your region to use the proper font.")
71
72 dsk_size   = getDesktop(0).size()
73 dsk_width  = dsk_size.width()
74 dsk_height = dsk_size.height()  
75
76 MIN_W = 400
77 MIN_H = 300
78
79 NAV_MODE_TEXT          = 0
80 NAV_MODE_SIZE_TEXT     = 1
81 NAV_MODE_SIZE_TIP_TEXT = 2
82
83 config.plugins.TeleText = ConfigSubsection()
84 config.plugins.TeleText.brightness   = ConfigSlider(default=8,  increment=1, limits=(0,15))
85 config.plugins.TeleText.contrast     = ConfigSlider(default=12, increment=1, limits=(0,15))
86 config.plugins.TeleText.transparency = ConfigSlider(default=8,  increment=1, limits=(0,15))
87 config.plugins.TeleText.messages = ConfigEnableDisable(default=True)
88 config.plugins.TeleText.edge_cut = ConfigEnableDisable(default=False)
89 config.plugins.TeleText.splitting_mode = ConfigSelection(splittingModeList, default=SPLIT_MODE_PAT)
90 config.plugins.TeleText.textlevel      = ConfigSelection(textlevelModeList, default="2")
91 config.plugins.TeleText.region   = ConfigSelection(regionList, default="16")
92 config.plugins.TeleText.debug    = ConfigEnableDisable(default=False)
93 config.plugins.TeleText.pos      = ConfigSequence(default=[0, 0, dsk_width, dsk_height], seperator = ",", limits = [(0,dsk_width>>3),(0,dsk_height>>3),(dsk_width-(dsk_width>>3),dsk_width),(dsk_height-(dsk_height>>3),dsk_height)])
94 config.plugins.TeleText.tip_pos  = ConfigSequence(default=[(dsk_width>>1)+(dsk_width>>2), (dsk_height>>1)+(dsk_height>>2), dsk_width, dsk_height], seperator = ",", limits = [(0,dsk_width-MIN_W),(0,dsk_height-MIN_H),(MIN_W,dsk_width),(MIN_H,dsk_height)])
95 # state
96 config.plugins.TeleText.textOnly = ConfigEnableDisable(default=True)
97 config.plugins.TeleText.opaque   = ConfigEnableDisable(default=False)
98
99 # global functions
100
101 def log(message):
102   _log(message)
103   if config.plugins.TeleText.debug.value:
104     _debug(message)
105
106 class TeleText(Screen):
107
108   isDM7025    = False
109   pageInput   = 0
110   hasText     = False
111   catchPage   = False
112   flofValue   = True
113   infoValue   = False
114   edgeValue   = False
115   opaqueValue = False
116   nav_mode    = NAV_MODE_TEXT
117   zoom        = TeletextInterface.MODE_FULL
118
119   onChangedEntry = [ ]  
120
121   def __init__(self, session):
122     TeleText.skin = """<screen position="0,0" size="%d,%d" title="TeleText" flags="wfNoBorder"/>""" % (dsk_width, dsk_height)
123     Screen.__init__(self, session)
124
125     self.__event_tracker = ServiceEventTracker(screen = self, eventmap={
126       iPlayableService.evStart : self.serviceStarted,
127       iPlayableService.evEnd : self.serviceStopped,
128       iPlayableService.evUpdatedInfo : self.serviceInfoChanged,
129     })
130
131     self["actions"] = NumberActionMap(["OkCancelActions", "TeleTextActions"],
132     {
133       "ok" : self.okPressed,
134       "cancel" : self.cancelPressed,
135       "1" : self.keyNumberGlobal,
136       "2" : self.keyNumberGlobal,
137       "3" : self.keyNumberGlobal,
138       "4" : self.keyNumberGlobal,
139       "5" : self.keyNumberGlobal,
140       "6" : self.keyNumberGlobal,
141       "7" : self.keyNumberGlobal,
142       "8" : self.keyNumberGlobal,
143       "9" : self.keyNumberGlobal,
144       "0" : self.keyNumberGlobal,
145       "red":    self.redPressed,
146       "green":  self.greenPressed,
147       "yellow": self.yellowPressed,
148       "blue":   self.bluePressed,
149       "right":  self.rightPressed,
150       "left":   self.leftPressed,
151       "down":   self.downPressed,
152       "up":     self.upPressed,
153       "info":   self.infoPressed,
154       "tv":     self.tvPressed,
155       "radio":  self.radioPressed,
156       "text":   self.textPressed,
157       "menu":   self.menuPressed,
158       "help":   self.helpPressed,
159       "video":  self.videoPressed,
160       "nextBouquet": self.nextBouquetPressed,
161       "prevBouquet": self.prevBouquetPressed,
162       "volUp":       self.volumeUpPressed,
163       "volDown":     self.volumeDownPressed
164     }, -1)
165     self["actions"].setEnabled(True)
166
167     self.helpList.append((self["actions"], "TeleTextActions", [("1", _("enter page number"))]))
168     self.helpList.append((self["actions"], "TeleTextActions", [("2", _("enter page number"))]))
169     self.helpList.append((self["actions"], "TeleTextActions", [("3", _("enter page number"))]))
170     self.helpList.append((self["actions"], "TeleTextActions", [("4", _("enter page number"))]))
171     self.helpList.append((self["actions"], "TeleTextActions", [("5", _("enter page number"))]))
172     self.helpList.append((self["actions"], "TeleTextActions", [("6", _("enter page number"))]))
173     self.helpList.append((self["actions"], "TeleTextActions", [("7", _("enter page number"))]))
174     self.helpList.append((self["actions"], "TeleTextActions", [("8", _("enter page number"))]))
175     self.helpList.append((self["actions"], "TeleTextActions", [("9", _("enter page number / page 100"))]))
176     self.helpList.append((self["actions"], "TeleTextActions", [("0", _("enter page number / rezap"))]))
177     self.helpList.append((self["actions"], "OkCancelActions", [("cancel", _("exit"))]))
178     self.helpList.append((self["actions"], "OkCancelActions", [("ok", _("start page catching / select page"))]))
179 #    self.helpList.append((self["actions"], "TeleTextActions", [("volUp",_("increase width"))]))
180 #    self.helpList.append((self["actions"], "TeleTextActions", [("volDown",_("decrease width"))]))
181     self.helpList.append((self["actions"], "TeleTextActions", [("nextBouquet",_("zoom / increase height"))]))
182     self.helpList.append((self["actions"], "TeleTextActions", [("prevBouquet",_("decrease height"))]))
183     self.helpList.append((self["actions"], "TeleTextActions", [("info", _("toggle info"))]))
184     self.helpList.append((self["actions"], "TeleTextActions", [("menu", _("teletext settings"))]))
185     self.helpList.append((self["actions"], "TeleTextActions", [("up", _("next page / catch page / move"))]))
186     self.helpList.append((self["actions"], "TeleTextActions", [("left", _("prev sub page / move"))]))
187     self.helpList.append((self["actions"], "TeleTextActions", [("right", _("next sub page / move"))]))
188     self.helpList.append((self["actions"], "TeleTextActions", [("down", _("prev page / catch page / move"))]))
189     self.helpList.append((self["actions"], "TeleTextActions", [("video", _("toggle flof"))]))
190     self.helpList.append((self["actions"], "TeleTextActions", [("red", _("red teletext link"))]))
191     self.helpList.append((self["actions"], "TeleTextActions", [("green", _("green teletext link"))]))
192     self.helpList.append((self["actions"], "TeleTextActions", [("yellow", _("yellow teletext link"))]))
193     self.helpList.append((self["actions"], "TeleTextActions", [("blue", _("blue teletext link"))]))
194     self.helpList.append((self["actions"], "TeleTextActions", [("tv", _("split screen"))]))
195     self.helpList.append((self["actions"], "TeleTextActions", [("radio", _("toggle transparency"))]))
196     self.helpList.append((self["actions"], "TeleTextActions", [("text", _("exit"))]))
197
198     self.connected = False
199
200     self.ttx = TeletextInterface()
201
202     self.onLayoutFinish.append(self.__layoutFinished)
203     self.onExecBegin.append(self.__execBegin)
204     self.onClose.append(self.__closed)
205
206     self.socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
207     self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
208     try:
209       unlink('/tmp/dbttcp.socket')
210     except:
211       pass
212     self.socket.bind('/tmp/dbttcp.socket')
213     self.listen_sn = eSocketNotifier(self.socket.fileno(), POLLIN)
214     self.listen_sn.callback.append(self.listen_data_avail)
215     self.socket.listen(1)
216
217   def socketSend(self, buf):
218     log("send %s" % (buf))
219     try:
220       s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
221       s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
222       s.connect('/tmp/dbttcd.socket')
223       s.setblocking(0)
224       s.sendall(buf)
225       s.close()
226     except socket.error, msg:
227       log("couldn't send data to /tmp/dbttcd.socket")
228       log(socket.errno)
229       log(msg)
230 #      self.session.open(MessageBox, _("Daemon not running."), MessageBox.TYPE_ERROR, timeout = 3)
231 #      self.close()
232
233   def listen_data_avail(self, what):
234     conn, addr = self.socket.accept()
235     buf = conn.recv(8, socket.MSG_WAITALL)
236     x = array.array('H')
237     x.fromstring(buf)
238     if (x[0] + x[1] + x[2] + x[3]) == 0:
239       self.catchPage = False
240     else:
241 #      if (x[0] + x[1]) == 0:
242 #        log("recv update %s" % (x))
243       if not self.isDM7025:
244         self.ttx.update(x[0], x[1], x[2], x[3], self.zoom);
245       conn.close()
246
247   def __execBegin(self):
248     log("execBegin")
249
250     self.updateLayout()
251
252     # send brightness, contrast and transparency...
253     self.sendSettings()
254
255     if self.isDM7025:
256       renderOffset = 0x75488
257       stride = 0xb80
258     else:
259       renderOffset = self.ttx.getRenderBufferOffset()
260       stride = self.ttx.getRenderBufferStride()
261
262     log("framebuffer offset is %08x stride is %08x" % (renderOffset, stride))
263     x = array.array('B', (CMD_RQ_UPDATE, 1, (renderOffset&0xFF000000)>>24, (renderOffset&0xFF0000)>>16, (renderOffset&0xFF00)>>8, renderOffset&0xFF, (stride&0xFF00) >> 8, stride&0xFF))
264     self.socketSend(x)
265
266   def __closed(self):
267     log("__closed")
268     if self.isDM7025:
269       renderOffset = 0x75488
270       stride = 0xb80
271     else:
272       renderOffset = self.ttx.getRenderBufferOffset()
273       stride = self.ttx.getRenderBufferStride()
274     x = array.array('B', (CMD_RQ_UPDATE, 0, (renderOffset&0xFF000000)>>24, (renderOffset&0xFF0000)>>16, (renderOffset&0xFF00)>>8, renderOffset&0xFF, (stride&0xFF00) >> 8, stride&0xFF))
275     self.socketSend(x)
276
277   def __layoutFinished(self):
278     log("__layoutFinished")
279     self.ttx.show(self.instance)
280
281   def keyNumberGlobal(self, number):
282     if self.nav_mode != NAV_MODE_TEXT or self.catchPage:
283       return
284     log("%s pressed" % (number))
285     x = array.array('B')
286     if self.pageInput == 0:
287       if number == 0:
288         x.append(CMD_RZAP_PAGE)
289       elif number == 9:
290         x.fromlist([CMD_SHOW_PAGE, 1, 0, 0])
291       else:
292         x.fromlist([CMD_PAGEINPUT, number])
293         self.pageInput = (self.pageInput + 1) % 3
294     else:
295       x.fromlist([CMD_PAGEINPUT, number])
296       self.pageInput = (self.pageInput + 1) % 3
297     self.socketSend(x)
298
299   def pageSet(self, page):
300     log("pageSet(%d)" % (page))
301     page = int("%d" % (page), 16)
302     x = array.array('B', (CMD_SHOW_PAGE, (page & 0xFF00) >> 8, (page&0xFF), 0))
303     self.socketSend(x)
304
305   def upPressed(self):
306     if self.nav_mode == NAV_MODE_TEXT:
307       if self.pageInput != 0:
308         return
309       log("up pressed")
310       if self.catchPage:
311         x = array.array('B', (CMD_CATCHPAGE, 2, 0))
312       else:
313         if self.zoom == TeletextInterface.MODE_LOWER_HALF:
314           self.zoom = TeletextInterface.MODE_UPPER_HALF
315         x = array.array('B')
316         x.append(CMD_PAGE_NEXT)
317       self.socketSend(x)
318     else:
319       if self.nav_pos[1] > 0 and self.nav_pos[3] > self.nav_config.limits[3][0]:
320         self.nav_pos[1] = self.nav_pos[1] - 1
321         self.nav_pos[3] = self.nav_pos[3] - 1
322       self.updateLayout()
323
324   def downPressed(self):
325     if self.nav_mode == NAV_MODE_TEXT:
326       if self.pageInput != 0:
327         return
328       log("down pressed")
329       if self.catchPage:
330         x = array.array('B', (CMD_CATCHPAGE, 2, 1))
331       else:
332         if self.zoom == TeletextInterface.MODE_LOWER_HALF:
333           self.zoom = TeletextInterface.MODE_UPPER_HALF
334         x = array.array('B')
335         x.append(CMD_PAGE_PREV)
336       self.socketSend(x)
337     else:
338       if self.nav_pos[1] < self.nav_config.limits[1][1] and self.nav_pos[3] < dsk_height:
339         self.nav_pos[1] = self.nav_pos[1] + 1
340         self.nav_pos[3] = self.nav_pos[3] + 1
341         self.updateLayout()
342
343   def leftPressed(self):
344     if self.nav_mode == NAV_MODE_TEXT:
345       if self.catchPage or self.pageInput != 0:
346         return
347       log("left pressed")
348       if self.zoom == TeletextInterface.MODE_LOWER_HALF:
349         self.zoom = TeletextInterface.MODE_UPPER_HALF
350       x = array.array('B')
351       x.append(CMD_SUBP_PREV)
352       self.socketSend(x)
353     else:
354       if self.nav_pos[0] > 0 and self.nav_pos[2] > self.nav_config.limits[2][0]:
355         self.nav_pos[0] = self.nav_pos[0] - 1
356         self.nav_pos[2] = self.nav_pos[2] - 1
357       self.updateLayout()
358
359   def rightPressed(self):
360     if self.nav_mode == NAV_MODE_TEXT:
361       if self.catchPage or self.pageInput != 0:
362         return
363       log("right pressed")
364       if self.zoom == TeletextInterface.MODE_LOWER_HALF:
365         self.zoom = TeletextInterface.MODE_UPPER_HALF
366       x = array.array('B')
367       x.append(CMD_SUBP_NEXT)
368       self.socketSend(x)
369     else:
370       if self.nav_pos[0] < self.nav_config.limits[0][1] and self.nav_pos[2] < dsk_width:
371         self.nav_pos[0] = self.nav_pos[0] + 1
372         self.nav_pos[2] = self.nav_pos[2] + 1
373         self.updateLayout()
374
375   def nextBouquetPressed(self):
376     log("bouqet+ pressed")
377     if self.nav_mode == NAV_MODE_TEXT:
378       if self.catchPage or self.pageInput != 0:
379         return
380       # zoom teletext
381       if self.zoom == TeletextInterface.MODE_UPPER_HALF:
382         self.zoom = TeletextInterface.MODE_LOWER_HALF
383       elif self.zoom == TeletextInterface.MODE_LOWER_HALF:
384         self.zoom = TeletextInterface.MODE_FULL
385       else:
386         self.zoom = TeletextInterface.MODE_UPPER_HALF
387     else:
388       # position setup
389       if self.nav_pos[3] < dsk_height:
390         self.nav_pos[3] = self.nav_pos[3] + 1
391       elif self.nav_pos[1] > 0:
392         self.nav_pos[1] = self.nav_pos[1] - 1
393     self.updateLayout()
394
395   def prevBouquetPressed(self):
396     if self.nav_mode == NAV_MODE_TEXT:
397       return
398     log("bouquet- pressed")
399     if self.nav_pos[3] > (self.nav_pos[1] + MIN_H):
400       if self.nav_pos[3] > self.nav_config.limits[3][0]:
401         self.nav_pos[3] = self.nav_pos[3] - 1
402       elif self.nav_pos[1] < self.nav_config.limits[1][1]:
403         self.nav_pos[1] = self.nav_pos[1] + 1
404       self.updateLayout()
405
406   def volumeUpPressed(self):
407     if self.nav_mode == NAV_MODE_TEXT:
408       globalActionMap.action("TeleText", "volumeUp")
409       return
410     log("volume+ pressed")
411     if self.nav_pos[2] < dsk_width:
412       self.nav_pos[2] = self.nav_pos[2] + 1
413     elif self.nav_pos[0] > 0:
414       self.nav_pos[0] = self.nav_pos[0] - 1
415     self.updateLayout()
416
417   def volumeDownPressed(self):
418     if self.nav_mode == NAV_MODE_TEXT:
419       globalActionMap.action("TeleText", "volumeDown")
420       return
421     log("volume- pressed")
422     if self.nav_pos[2] > (self.nav_pos[0] + MIN_W):
423       if self.nav_pos[2] > self.nav_config.limits[2][0]:
424         self.nav_pos[2] = self.nav_pos[2] - 1
425       elif self.nav_pos[0] < self.nav_config.limits[0][1]:
426         self.nav_pos[0] = self.nav_pos[0] + 1
427     self.updateLayout()
428
429   def redPressed(self):
430     if self.nav_mode != NAV_MODE_TEXT or self.catchPage or self.pageInput != 0:
431       return
432     log("red pressed")
433     x = array.array('B')
434     x.append(CMD_COLKEY_RD)
435     self.socketSend(x)
436
437   def greenPressed(self):
438     if self.nav_mode != NAV_MODE_TEXT or self.catchPage or self.pageInput != 0:
439       return
440     log("green pressed")
441     x = array.array('B')
442     x.append(CMD_COLKEY_GN)
443     self.socketSend(x)
444
445   def yellowPressed(self):
446     if self.nav_mode != NAV_MODE_TEXT or self.catchPage or self.pageInput != 0:
447       return
448     log("yellow pressed")
449     x = array.array('B')
450     x.append(CMD_COLKEY_YE)
451     self.socketSend(x)
452
453   def bluePressed(self):
454     if self.nav_mode != NAV_MODE_TEXT or self.catchPage or self.pageInput != 0:
455       return
456     log("blue pressed")
457     x = array.array('B')
458     x.append(CMD_COLKEY_BL)
459     self.socketSend(x)
460
461   def infoPressed(self):
462     if self.nav_mode != NAV_MODE_TEXT or self.catchPage or self.pageInput != 0:
463       return
464     log("info pressed")
465     self.infoValue = not self.infoValue
466     for i in self.onChangedEntry:
467       i()
468     x = array.array('B')
469     x.append(CMD_CONCEALED)
470     self.socketSend(x)
471
472   def videoPressed(self):
473     if self.nav_mode != NAV_MODE_TEXT or self.catchPage or self.pageInput != 0:
474       return
475     log("video pressed")
476     self.flofValue = not self.flofValue
477     for i in self.onChangedEntry:
478       i()
479     x = array.array('B')
480     x.append(CMD_FLOF)
481     self.socketSend(x)
482
483   def tvPressed(self):
484     if self.nav_mode != NAV_MODE_TEXT:
485       return
486     log("tv pressed")
487     if config.plugins.TeleText.textOnly.value:
488       config.plugins.TeleText.textOnly.value = False
489     else:
490       config.plugins.TeleText.textOnly.value = True
491     config.plugins.TeleText.textOnly.save()
492     configfile.save()
493     self.updateLayout()
494
495   def radioPressed(self):
496     if self.nav_mode != NAV_MODE_TEXT or self.catchPage or self.pageInput != 0:
497       return
498     log("radio pressed")
499     if config.plugins.TeleText.opaque.value:
500       config.plugins.TeleText.opaque.value = False
501     else:
502       config.plugins.TeleText.opaque.value = True
503     config.plugins.TeleText.opaque.save()
504     configfile.save()
505     self.opaqueValue = config.plugins.TeleText.opaque.value
506     x = array.array('B')
507     x.append(CMD_OPAQUE)
508     self.socketSend(x)
509
510   def textPressed(self):
511     if self.nav_mode != NAV_MODE_TEXT or self.catchPage or self.pageInput != 0:
512       return
513     log("text pressed")
514     self.resetVideo()
515     self.__closed()
516     self.close()
517
518   def menuPressed(self):
519     if self.nav_mode != NAV_MODE_TEXT or self.catchPage or self.pageInput != 0:
520       return
521     log("menu pressed")
522     self.__closed()
523     self.resetVideo()
524     self.session.openWithCallback(self.menuResult, TeleTextMenu)
525
526   def menuResult(self, result):
527     if result is None:
528       return
529     
530     self.nav_text_only = config.plugins.TeleText.textOnly.value
531     self.nav_config = result
532     self.nav_orig_pos   = result.value
533     self.nav_pos    = result.value
534     
535     if result == config.plugins.TeleText.pos:
536       self.nav_mode = NAV_MODE_SIZE_TEXT
537       config.plugins.TeleText.textOnly.value = True
538     elif result == config.plugins.TeleText.tip_pos:
539       self.nav_mode = NAV_MODE_SIZE_TIP_TEXT
540       config.plugins.TeleText.textOnly.value = False
541       config.plugins.TeleText.textOnly.value = SPLIT_MODE_TIP
542     self.updateLayout()
543
544   def updateLayout(self):
545     if self.nav_mode == NAV_MODE_TEXT:
546       pos = config.plugins.TeleText.pos.value
547     else:
548       pos = self.nav_pos
549     right  = pos[2]
550     bottom = pos[3]
551     mode = config.plugins.TeleText.splitting_mode.value
552
553     if config.plugins.TeleText.textOnly.value == True:
554       left  = pos[0]
555       width  = right - left
556       top    = pos[1]
557       height = bottom - top
558       self.resetVideo()
559     elif mode == SPLIT_MODE_PAT:
560       left   = dsk_width>>1
561       width  = right - (dsk_width>>1)
562       top    = pos[1]
563       height = bottom - top
564       log("splitting video")
565       l=open("/proc/stb/vmpeg/0/dst_left","w")
566       l.write("%x" % 0)
567       l.close()
568       w=open("/proc/stb/vmpeg/0/dst_width","w")
569       w.write("%x" % 360)
570       w.close()
571     elif mode == SPLIT_MODE_TAP:
572       left   = pos[0]
573       width  = (dsk_width>>1) - left
574       top    = pos[1]
575       height = bottom - top
576       log("splitting video")
577       l=open("/proc/stb/vmpeg/0/dst_left","w")
578       l.write("%x" % 360)
579       l.close()
580       w=open("/proc/stb/vmpeg/0/dst_width","w")
581       w.write("%x" % 360)
582       w.close()
583     elif mode == SPLIT_MODE_TIP:
584       if self.nav_mode == NAV_MODE_TEXT:
585         pos = config.plugins.TeleText.tip_pos.value
586       left   = pos[0]
587       width  = pos[2] - left
588       top    = pos[1]
589       height = pos[3] - top
590       self.resetVideo()
591
592     log("screen rect %s %s %s %s" % (left, top, width, height))
593     self.instance.move(ePoint(left,top))
594     self.instance.resize(eSize(*(width, height)))
595
596     self.ttx.hide()
597     self.ttx.show(self.instance)
598     self.ttx.update(0,0,492,250,self.zoom)
599
600   def resetVideo(self):
601     log("reset video")
602     l=open("/proc/stb/vmpeg/0/dst_left","w")
603     l.write("%x" % 0)
604     l.close()
605     w=open("/proc/stb/vmpeg/0/dst_width","w")
606     w.write("%x" % 720)
607     w.close()
608
609   def sendSettings(self, result = True):
610     if result:
611       # region
612       x = array.array('B')
613       x.append(CMD_REGION)
614       x.append(int(config.plugins.TeleText.region.value))
615       self.socketSend(x)
616       # Helligkeit
617       x = array.array('B')
618       x.append(CMD_SET_BRIGH)
619       x.append(config.plugins.TeleText.brightness.value<<4)
620       self.socketSend(x)
621       # Kontrast
622       x = array.array('B')
623       x.append(CMD_SET_CONTR)
624       x.append(config.plugins.TeleText.contrast.value<<4)
625       self.socketSend(x)
626       # Transparenz
627       x = array.array('B')
628       x.append(CMD_TRANSPARENCY)
629       x.append(config.plugins.TeleText.transparency.value<<4)
630       self.socketSend(x)
631       # edge cut
632       if self.edgeValue != config.plugins.TeleText.edge_cut.value:
633         self.edgeValue = config.plugins.TeleText.edge_cut.value
634         x = array.array('B')
635         x.append(CMD_EDGE_CUT)
636         self.socketSend(x)
637       # teletext level
638       x = array.array('B')
639       x.append(CMD_TEXTLEVEL)
640       x.append(int(config.plugins.TeleText.textlevel.value))
641       self.socketSend(x)
642       # opaque
643       if self.opaqueValue != config.plugins.TeleText.opaque.value:
644         self.opaqueValue = config.plugins.TeleText.opaque.value
645         x = array.array('B')
646         x.append(CMD_OPAQUE)
647         self.socketSend(x)
648
649   def helpPressed(self):
650     self.__closed()
651     self.resetVideo()
652     self.session.open(HelpMenu, self.helpList)     
653
654   def okPressed(self):
655     if self.nav_mode == NAV_MODE_TEXT:
656       if self.pageInput != 0:
657         return
658       log("ok pressed")
659       if self.catchPage:
660         x = array.array('B', (CMD_CATCHPAGE, 3, 1))
661         self.catchPage = False
662       else:
663         x = array.array('B', (CMD_CATCHPAGE, 1, 0))
664         self.catchPage = True
665         self.zoom = TeletextInterface.MODE_FULL
666       self.socketSend(x)
667     else:
668       if self.nav_mode == NAV_MODE_SIZE_TEXT:
669         config.plugins.TeleText.pos.value = self.nav_pos
670         config.plugins.TeleText.pos.save()
671       else:
672         config.plugins.TeleText.tip_pos.value = self.nav_pos
673         config.plugins.TeleText.tip_pos.save()
674       config.plugins.TeleText.textOnly.value = self.nav_text_only
675       del self.nav_text_only
676       del self.nav_config
677       del self.nav_orig_pos
678       del self.nav_pos
679       self.nav_mode = NAV_MODE_TEXT
680       self.updateLayout()
681
682   def cancelPressed(self):
683     if self.nav_mode == NAV_MODE_TEXT:
684       if self.pageInput != 0:
685         return
686       log("cancel pressed")
687       if self.catchPage:
688         x = array.array('B', (CMD_CATCHPAGE, 3, 0))
689         self.socketSend(x)
690         self.catchPage = False
691       else:
692         self.resetVideo()
693         self.__closed()
694         self.close()
695     else:
696       if self.nav_mode == NAV_MODE_SIZE_TEXT:
697         config.plugins.TeleText.pos.cancel()
698       else:
699         config.plugins.TeleText.tip_pos.cancel()
700       config.plugins.TeleText.textOnly.value = self.nav_text_only
701       del self.nav_text_only
702       del self.nav_config
703       del self.nav_orig_pos
704       del self.nav_pos
705       self.nav_mode = NAV_MODE_TEXT
706       self.updateLayout()
707
708   def serviceStarted(self):
709     log("service started")
710
711   def serviceStopped(self):
712     log("service stopped")
713     x = array.array('B', (CMD_CTL_CACHE, 0, 0, 0))
714     self.socketSend(x)
715
716   def serviceInfoChanged(self):
717     log("serviceInfoChanged")
718     service = self.session.nav.getCurrentService()
719     info = service and service.info()
720     txtpid = info and info.getInfo(iServiceInformation.sTXTPID)
721
722     self.hasText = txtpid is not None and txtpid > -1
723
724     stream = service and service.stream()
725     demux = stream and stream.getStreamingData()
726     demux = demux and demux.get("demux", -1)
727
728     log("TXT PID %s DEMUX %s" % (txtpid, demux))
729
730     if demux > -1 and self.hasText:
731       x = array.array('B', (CMD_CTL_CACHE, (txtpid & 0xFF00) >> 8, (txtpid&0xFF), demux))
732       self.socketSend(x)
733
734   def showMessages(self):
735     return config.plugins.TeleText.messages.value
736
737   # ---- for summary (lcd) ----
738
739   def createSummary(self):
740     return TeleTextSummary
741
742   def flofEnabled(self):
743     return self.flofValue
744     
745   def infoEnabled(self):
746     return self.infoValue
747
748 # ----------------------------------------
749
750 class TeleTextSummary(Screen):
751
752   def __init__(self, session, parent):
753     onPic  = resolveFilename(SCOPE_PLUGINS, "Extensions/TeleText/lcd_on.png")
754     offPic = resolveFilename(SCOPE_PLUGINS, "Extensions/TeleText/lcd_off.png")
755
756     TeleTextSummary.skin = """<screen name="TeleTextSummary" position="0,0" size="132,64">
757       <widget name="SetupTitle" position="6,4" size="120,20" font="Regular;20" halign="center"/>
758
759       <widget name="flof_off" position="24,28" size="20,20" pixmap="%s" zPosition="1"/>
760       <widget name="info_off" position="88,28" size="20,20" pixmap="%s" zPosition="1"/>
761       <widget name="flof_on"  position="24,28" size="20,20" pixmap="%s" zPosition="2"/>
762       <widget name="info_on"  position="88,28" size="20,20" pixmap="%s" zPosition="2"/>
763
764       <widget name="flof_txt" position="10,50" size="48,12" font="Regular;12" valign="center" halign="center" zPosition="1"/>
765       <widget name="info_txt" position="74,50" size="48,12" font="Regular;12" valign="center" halign="center" zPosition="1"/> 
766     </screen>""" % (offPic, offPic, onPic, onPic)
767
768     Screen.__init__(self, session, parent = parent)
769     self["SetupTitle"] = Label("TeleText")
770     self["flof_txt"] = Label("FLOF")
771     self["info_txt"] = Label("INFO")
772     self["flof_off"] = Pixmap()
773     self["info_off"] = Pixmap()
774     self["flof_on"]  = Pixmap()
775     self["info_on"]  = Pixmap()
776     self.onShow.append(self.addWatcher)
777     self.onHide.append(self.removeWatcher)
778
779   def addWatcher(self):
780     self.parent.onChangedEntry.append(self.selectionChanged)
781     self.selectionChanged()
782
783   def removeWatcher(self):
784     self.parent.onChangedEntry.remove(self.selectionChanged)
785
786   def selectionChanged(self):
787     if self.parent.flofEnabled():
788       self["flof_off"].hide()
789       self["flof_on"].show()
790     else:
791       self["flof_on"].hide()
792       self["flof_off"].show()
793
794     if self.parent.infoEnabled():
795       self["info_off"].hide()
796       self["info_on"].show()
797     else:
798       self["info_on"].hide()
799       self["info_off"].show()
800
801 # ----------------------------------------
802
803 class TeleTextMenu(ConfigListScreen, Screen):
804
805   onChangedEntry = [ ]
806   isInitialized = False
807
808   def __init__(self, session):
809     width = 492
810     height = 400
811     left = (dsk_width - width)>>1
812     top = (dsk_height - height)>>1
813     log("[menu] screen rect %s %s %s %s" % (left, top, width, height))
814     TeleTextMenu.skin = """<screen position="%d,%d" size="%d,%d" title="%s">
815         <ePixmap pixmap="skin_default/buttons/red.png"    position="0,0"   zPosition="0" size="140,40" transparent="1" alphatest="on" />
816         <ePixmap pixmap="skin_default/buttons/yellow.png" position="176,0" zPosition="0" size="140,40" transparent="1" alphatest="on" />
817         <ePixmap pixmap="skin_default/buttons/green.png"  position="352,0" zPosition="0" size="140,40" transparent="1" alphatest="on" />
818         <widget render="Label" source="key_r" position="0,0"   size="140,40" zPosition="5" valign="center" halign="center" backgroundColor="red" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
819         <widget render="Label" source="key_y" position="176,0" size="140,40" zPosition="5" valign="center" halign="center" backgroundColor="red" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
820         <widget render="Label" source="key_g" position="352,0" size="140,40" zPosition="5" valign="center" halign="center" backgroundColor="red" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
821         <widget name="config" position="0,50"   size="492,275" scrollbarMode="showOnDemand" zPosition="1"/>
822         <ePixmap pixmap="skin_default/div-h.png" position="0,330" zPosition="1" size="492,2" />
823         <widget name="label"  position="0,335" size="492,65" font="Regular;16" zPosition="1" halign="left" valign="top"/>
824       </screen>""" % (left, top, width, height, _("TeleText settings"))
825
826     Screen.__init__(self, session)
827
828     # create config list
829     self.list = [] 
830     ConfigListScreen.__init__(self, self.list) 
831     self.createConfigList()
832
833     self["actions"] = ActionMap(["OkCancelActions", "TeleTextActions"],
834     {
835       "ok"     : self.okPressed,
836       "cancel" : self.cancelPressed,
837       "red"    : self.cancelPressed,
838       "green"  : self.okPressed,
839       "yellow" : self.resetPressed,
840       "menu"   : self.cancelPressed,
841       "text"   : self.textPressed
842     }, -2)
843     self["actions"].setEnabled(True)
844
845     self["label"] = Label("Info")
846     self["key_r"] = StaticText(_("Cancel"))
847     self["key_y"] = StaticText(_("Default"))
848     self["key_g"] = StaticText(_("OK")) 
849     self.onLayoutFinish.append(self.__layoutFinished)
850
851   def __layoutFinished(self):
852     self.isInitialized = True
853     if not self.selectionChanged in self["config"].onSelectionChanged:
854       self["config"].onSelectionChanged.append(self.selectionChanged)
855     self.selectionChanged()     
856
857   def selectionChanged(self):
858     configele = self["config"].getCurrent()[1]
859     if configele == config.plugins.TeleText.pos:
860       self["label"].setText(HELP_TEXT_POS)
861     elif configele == config.plugins.TeleText.brightness:
862       self["label"].setText(HELP_TEXT_BRIGHTNESS)
863     elif configele == config.plugins.TeleText.contrast:
864       self["label"].setText(HELP_TEXT_CONTRAST)
865     elif configele == config.plugins.TeleText.transparency:
866       self["label"].setText(HELP_TEXT_TRANSPARENCY)
867     elif configele == config.plugins.TeleText.splitting_mode:
868       self["label"].setText(HELP_TEXT_SPLITTING)
869     elif configele == config.plugins.TeleText.tip_pos:
870       self["label"].setText(HELP_TEXT_TIP_POS)
871     elif configele == config.plugins.TeleText.messages:
872       self["label"].setText(HELP_TEXT_MESSAGES)
873     elif configele == config.plugins.TeleText.debug:
874       self["label"].setText(HELP_TEXT_DEBUG)
875     elif configele == config.plugins.TeleText.edge_cut:
876       self["label"].setText(HELP_TEXT_EDGE_CUT)
877     elif configele == config.plugins.TeleText.textlevel:
878       self["label"].setText(HELP_TEXT_TEXTLEVEL)
879     elif configele == config.plugins.TeleText.region:
880       self["label"].setText(HELP_TEXT_REGION)
881
882   def createConfig(self, configele):
883     if not self.isInitialized:
884       return
885     self.createConfigList()
886
887   def createConfigList(self):
888     self.isInitialized = False
889
890     # remove notifiers
891     for x in self["config"].list:
892       x[1].clearNotifiers() 
893
894     self.list = [
895       getConfigListEntry(_("Brightness"),        config.plugins.TeleText.brightness),
896       getConfigListEntry(_("Contrast"),          config.plugins.TeleText.contrast),
897       getConfigListEntry(_("Transparency"),      config.plugins.TeleText.transparency),
898       getConfigListEntry(_("Text level"),        config.plugins.TeleText.textlevel),
899       getConfigListEntry(_("Region"),            config.plugins.TeleText.region),
900       getConfigListEntry(_("Position and size"), config.plugins.TeleText.pos),
901       getConfigListEntry(_("Display edges"),     config.plugins.TeleText.edge_cut),
902       getConfigListEntry(_("Splitting mode"),    config.plugins.TeleText.splitting_mode)
903     ]
904     if config.plugins.TeleText.splitting_mode.value == SPLIT_MODE_TIP:
905       self.list.append(getConfigListEntry("... %s" % _("Position and size"),   config.plugins.TeleText.tip_pos))
906     self.list.append(getConfigListEntry(_("Message"), config.plugins.TeleText.messages))
907     self.list.append(getConfigListEntry(_("Debug"),   config.plugins.TeleText.debug))
908
909     self["config"].list = self.list
910
911     # add notifiers (lcd, info)
912     for x in self["config"].list:
913       x[1].addNotifier(self.changedEntry)
914     # add notifiers (menu)
915     config.plugins.TeleText.splitting_mode.addNotifier(self.createConfig)
916
917     self.isInitialized = True
918
919   def resetPressed(self):
920     log("[menu] reset pressed")
921     config.plugins.TeleText.brightness.setValue(8)
922     config.plugins.TeleText.contrast.setValue(12)
923     config.plugins.TeleText.transparency.setValue(8)
924     config.plugins.TeleText.messages.setValue(True)
925     config.plugins.TeleText.edge_cut.setValue(False)
926     config.plugins.TeleText.splitting_mode.setValue(SPLIT_MODE_PAT)
927     config.plugins.TeleText.textlevel.setValue("2")
928     config.plugins.TeleText.region.setValue("16")
929     config.plugins.TeleText.debug.setValue(False)
930     config.plugins.TeleText.pos.setValue([0, 0, dsk_width, dsk_height])
931     config.plugins.TeleText.tip_pos.setValue([(dsk_width>>1)+(dsk_width>>2), (dsk_height>>1)+(dsk_height>>2), dsk_width, dsk_height])
932
933   def textPressed(self):
934     log("[menu] text pressed")
935     if self["config"].getCurrent()[1] == config.plugins.TeleText.pos:
936       self.close(config.plugins.TeleText.pos)
937     elif self["config"].getCurrent()[1] == config.plugins.TeleText.tip_pos:
938       self.close(config.plugins.TeleText.tip_pos)
939
940   def okPressed(self):
941     log("[menu] ok pressed")
942     self.checkPositionValues(config.plugins.TeleText.pos)
943     self.checkPositionValues(config.plugins.TeleText.tip_pos)
944     for x in self["config"].list:
945       x[1].save()
946     configfile.save()
947     self.close(None) 
948
949   def checkPositionValues(self, configele):
950     pos = configele.value
951     log("... old pos: %s %s %s %s" % (pos[0], pos[1], pos[2], pos[3]))
952     update = False
953     if pos[0] > pos[2]:
954       i = pos[0]
955       pos[0] = pos[2]
956       pos[2] = i
957       update = True
958     if pos[1] > pos[3]:
959       i = pos[1]
960       pos[1] = pos[3]
961       pos[3] = i
962       update = True
963     if (pos[2] - pos[0]) < MIN_W:
964       pos[2] = pos[0] + MIN_W
965       update = True
966     if (pos[3] - pos[1]) < MIN_H:
967       pos[3] = pos[1] + MIN_H
968       update = True
969     if pos[2] > dsk_width:
970       pos[0] = pos[0] + dsk_width - pos[2]
971       pos[2] = dsk_width
972       update = True
973     if pos[3] > dsk_height:
974       pos[1] = pos[1] + dsk_height - pos[3]
975       pos[3] = dsk_height
976       update = True
977     log("... new pos: %s %s %s %s" % (pos[0], pos[1], pos[2], pos[3]))
978       
979     if update:
980       configele.setValue(pos)
981
982   def cancelPressed(self):
983     log("[menu] cancel pressed")
984     confirm = False
985     for x in self["config"].list:
986       confirm = confirm or x[1].isChanged()
987     if confirm:
988       self.session.openWithCallback(self.DiscardConfirm, MessageBox, _("Discard changes?"))
989     else:
990       self.close(None) 
991
992   def DiscardConfirm(self, result):
993     if result:
994       for x in self["config"].list:
995         if x[1].isChanged():
996           x[1].cancel()
997       self.close(None)
998
999   # ---- for summary (lcd) ----
1000
1001   def changedEntry(self, element=None):
1002     for x in self.onChangedEntry:
1003       x()
1004
1005   def getCurrentEntry(self):
1006     return self["config"].getCurrent()[0]
1007
1008   def getCurrentValue(self):
1009     return str(self["config"].getCurrent()[1].getText())
1010
1011   def createSummary(self):
1012     return TeleTextMenuSummary
1013
1014 # ----------------------------------------
1015
1016 class TeleTextMenuSummary(Screen):
1017   skin = """<screen name="TeleTextMenuSummary" position="0,0" size="132,64">
1018       <widget name="SetupTitle" position="6,4"  size="120,20" font="Regular;20" halign="center"/>
1019       <widget name="SetupEntry" position="6,30" size="120,12" font="Regular;12" halign="left"/>
1020       <widget name="SetupValue" position="6,48" size="120,12" font="Regular;12" halign="right"/>
1021     </screen>"""
1022
1023   def __init__(self, session, parent):
1024     Screen.__init__(self, session, parent = parent)
1025     self["SetupTitle"] = Label("TeleText")
1026     self["SetupEntry"] = Label("")
1027     self["SetupValue"] = Label("")
1028     self.onShow.append(self.addWatcher)
1029     self.onHide.append(self.removeWatcher)
1030
1031   def addWatcher(self):
1032     self.parent.onChangedEntry.append(self.selectionChanged)
1033     self.parent["config"].onSelectionChanged.append(self.selectionChanged)
1034     self.selectionChanged()
1035
1036   def removeWatcher(self):
1037     self.parent.onChangedEntry.remove(self.selectionChanged)
1038     self.parent["config"].onSelectionChanged.remove(self.selectionChanged)
1039
1040   def selectionChanged(self):
1041     self["SetupEntry"].text = self.parent.getCurrentEntry()
1042     self["SetupValue"].text = self.parent.getCurrentValue() 
1043
1044 # ----------------------------------------
1045
1046 def sessionstart(reason, session):
1047   log("----- sessionstart(%s) -----" % session)
1048   # Plugin initialisieren
1049   global ttx_screen;
1050   ttx_screen = session.instantiateDialog(TeleText)
1051
1052 def autostart(reason, **kwargs):
1053   log("autostart(%s, %s)" % (reason, kwargs))
1054   if reason == 0:
1055     pass
1056   elif reason == 1:
1057     pass
1058
1059 def mainText(session, **kwargs):
1060   global ttx_screen
1061   log("mainText")
1062   if ttx_screen.hasText:
1063     session.execDialog(ttx_screen)
1064   else:
1065     if ttx_screen.showMessages():
1066       session.open(MessageBox, _("No teletext available."), MessageBox.TYPE_INFO, timeout = 3)
1067
1068 def mainMenu(session, **kwargs):
1069   global ttx_screen
1070   log("mainMenu")
1071   session.open(TeleTextMenu)
1072
1073 def Plugins(**kwargs):
1074   log("plugins")
1075   return [
1076     PluginDescriptor(name="TeleText", description="teletext", where = PluginDescriptor.WHERE_TELETEXT, fnc=mainText),
1077     PluginDescriptor(needsRestart = False, where = PluginDescriptor.WHERE_SESSIONSTART, fnc=sessionstart),
1078     PluginDescriptor(needsRestart = False, where = PluginDescriptor.WHERE_AUTOSTART, fnc=autostart)
1079     ]
1080
1081 # EOF