[TeleText] fixed zoom mode while rezapping, changed menu layout
[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         if self.zoom == TeletextInterface.MODE_LOWER_HALF:
289           self.zoom = TeletextInterface.MODE_UPPER_HALF
290         x.append(CMD_RZAP_PAGE)
291       elif number == 9:
292         x.fromlist([CMD_SHOW_PAGE, 1, 0, 0])
293       else:
294         x.fromlist([CMD_PAGEINPUT, number])
295         self.pageInput = (self.pageInput + 1) % 3
296     else:
297       x.fromlist([CMD_PAGEINPUT, number])
298       self.pageInput = (self.pageInput + 1) % 3
299     self.socketSend(x)
300
301   def pageSet(self, page):
302     log("pageSet(%d)" % (page))
303     page = int("%d" % (page), 16)
304     x = array.array('B', (CMD_SHOW_PAGE, (page & 0xFF00) >> 8, (page&0xFF), 0))
305     self.socketSend(x)
306
307   def upPressed(self):
308     if self.nav_mode == NAV_MODE_TEXT:
309       if self.pageInput != 0:
310         return
311       log("up pressed")
312       if self.catchPage:
313         x = array.array('B', (CMD_CATCHPAGE, 2, 0))
314       else:
315         if self.zoom == TeletextInterface.MODE_LOWER_HALF:
316           self.zoom = TeletextInterface.MODE_UPPER_HALF
317         x = array.array('B')
318         x.append(CMD_PAGE_NEXT)
319       self.socketSend(x)
320     else:
321       if self.nav_pos[1] > 0 and self.nav_pos[3] > self.nav_config.limits[3][0]:
322         self.nav_pos[1] = self.nav_pos[1] - 1
323         self.nav_pos[3] = self.nav_pos[3] - 1
324       self.updateLayout()
325
326   def downPressed(self):
327     if self.nav_mode == NAV_MODE_TEXT:
328       if self.pageInput != 0:
329         return
330       log("down pressed")
331       if self.catchPage:
332         x = array.array('B', (CMD_CATCHPAGE, 2, 1))
333       else:
334         if self.zoom == TeletextInterface.MODE_LOWER_HALF:
335           self.zoom = TeletextInterface.MODE_UPPER_HALF
336         x = array.array('B')
337         x.append(CMD_PAGE_PREV)
338       self.socketSend(x)
339     else:
340       if self.nav_pos[1] < self.nav_config.limits[1][1] and self.nav_pos[3] < dsk_height:
341         self.nav_pos[1] = self.nav_pos[1] + 1
342         self.nav_pos[3] = self.nav_pos[3] + 1
343         self.updateLayout()
344
345   def leftPressed(self):
346     if self.nav_mode == NAV_MODE_TEXT:
347       if self.catchPage or self.pageInput != 0:
348         return
349       log("left pressed")
350       if self.zoom == TeletextInterface.MODE_LOWER_HALF:
351         self.zoom = TeletextInterface.MODE_UPPER_HALF
352       x = array.array('B')
353       x.append(CMD_SUBP_PREV)
354       self.socketSend(x)
355     else:
356       if self.nav_pos[0] > 0 and self.nav_pos[2] > self.nav_config.limits[2][0]:
357         self.nav_pos[0] = self.nav_pos[0] - 1
358         self.nav_pos[2] = self.nav_pos[2] - 1
359       self.updateLayout()
360
361   def rightPressed(self):
362     if self.nav_mode == NAV_MODE_TEXT:
363       if self.catchPage or self.pageInput != 0:
364         return
365       log("right pressed")
366       if self.zoom == TeletextInterface.MODE_LOWER_HALF:
367         self.zoom = TeletextInterface.MODE_UPPER_HALF
368       x = array.array('B')
369       x.append(CMD_SUBP_NEXT)
370       self.socketSend(x)
371     else:
372       if self.nav_pos[0] < self.nav_config.limits[0][1] and self.nav_pos[2] < dsk_width:
373         self.nav_pos[0] = self.nav_pos[0] + 1
374         self.nav_pos[2] = self.nav_pos[2] + 1
375         self.updateLayout()
376
377   def nextBouquetPressed(self):
378     log("bouqet+ pressed")
379     if self.nav_mode == NAV_MODE_TEXT:
380       if self.catchPage or self.pageInput != 0:
381         return
382       # zoom teletext
383       if self.zoom == TeletextInterface.MODE_UPPER_HALF:
384         self.zoom = TeletextInterface.MODE_LOWER_HALF
385       elif self.zoom == TeletextInterface.MODE_LOWER_HALF:
386         self.zoom = TeletextInterface.MODE_FULL
387       else:
388         self.zoom = TeletextInterface.MODE_UPPER_HALF
389     else:
390       # position setup
391       if self.nav_pos[3] < dsk_height:
392         self.nav_pos[3] = self.nav_pos[3] + 1
393       elif self.nav_pos[1] > 0:
394         self.nav_pos[1] = self.nav_pos[1] - 1
395     self.updateLayout()
396
397   def prevBouquetPressed(self):
398     if self.nav_mode == NAV_MODE_TEXT:
399       return
400     log("bouquet- pressed")
401     if self.nav_pos[3] > (self.nav_pos[1] + MIN_H):
402       if self.nav_pos[3] > self.nav_config.limits[3][0]:
403         self.nav_pos[3] = self.nav_pos[3] - 1
404       elif self.nav_pos[1] < self.nav_config.limits[1][1]:
405         self.nav_pos[1] = self.nav_pos[1] + 1
406       self.updateLayout()
407
408   def volumeUpPressed(self):
409     if self.nav_mode == NAV_MODE_TEXT:
410       globalActionMap.action("TeleText", "volumeUp")
411       return
412     log("volume+ pressed")
413     if self.nav_pos[2] < dsk_width:
414       self.nav_pos[2] = self.nav_pos[2] + 1
415     elif self.nav_pos[0] > 0:
416       self.nav_pos[0] = self.nav_pos[0] - 1
417     self.updateLayout()
418
419   def volumeDownPressed(self):
420     if self.nav_mode == NAV_MODE_TEXT:
421       globalActionMap.action("TeleText", "volumeDown")
422       return
423     log("volume- pressed")
424     if self.nav_pos[2] > (self.nav_pos[0] + MIN_W):
425       if self.nav_pos[2] > self.nav_config.limits[2][0]:
426         self.nav_pos[2] = self.nav_pos[2] - 1
427       elif self.nav_pos[0] < self.nav_config.limits[0][1]:
428         self.nav_pos[0] = self.nav_pos[0] + 1
429     self.updateLayout()
430
431   def redPressed(self):
432     if self.nav_mode != NAV_MODE_TEXT or self.catchPage or self.pageInput != 0:
433       return
434     log("red pressed")
435     x = array.array('B')
436     x.append(CMD_COLKEY_RD)
437     self.socketSend(x)
438
439   def greenPressed(self):
440     if self.nav_mode != NAV_MODE_TEXT or self.catchPage or self.pageInput != 0:
441       return
442     log("green pressed")
443     x = array.array('B')
444     x.append(CMD_COLKEY_GN)
445     self.socketSend(x)
446
447   def yellowPressed(self):
448     if self.nav_mode != NAV_MODE_TEXT or self.catchPage or self.pageInput != 0:
449       return
450     log("yellow pressed")
451     x = array.array('B')
452     x.append(CMD_COLKEY_YE)
453     self.socketSend(x)
454
455   def bluePressed(self):
456     if self.nav_mode != NAV_MODE_TEXT or self.catchPage or self.pageInput != 0:
457       return
458     log("blue pressed")
459     x = array.array('B')
460     x.append(CMD_COLKEY_BL)
461     self.socketSend(x)
462
463   def infoPressed(self):
464     if self.nav_mode != NAV_MODE_TEXT or self.catchPage or self.pageInput != 0:
465       return
466     log("info pressed")
467     self.infoValue = not self.infoValue
468     for i in self.onChangedEntry:
469       i()
470     x = array.array('B')
471     x.append(CMD_CONCEALED)
472     self.socketSend(x)
473
474   def videoPressed(self):
475     if self.nav_mode != NAV_MODE_TEXT or self.catchPage or self.pageInput != 0:
476       return
477     log("video pressed")
478     self.flofValue = not self.flofValue
479     for i in self.onChangedEntry:
480       i()
481     x = array.array('B')
482     x.append(CMD_FLOF)
483     self.socketSend(x)
484
485   def tvPressed(self):
486     if self.nav_mode != NAV_MODE_TEXT:
487       return
488     log("tv pressed")
489     if config.plugins.TeleText.textOnly.value:
490       config.plugins.TeleText.textOnly.value = False
491     else:
492       config.plugins.TeleText.textOnly.value = True
493     config.plugins.TeleText.textOnly.save()
494     configfile.save()
495     self.updateLayout()
496
497   def radioPressed(self):
498     if self.nav_mode != NAV_MODE_TEXT or self.catchPage or self.pageInput != 0:
499       return
500     log("radio pressed")
501     if config.plugins.TeleText.opaque.value:
502       config.plugins.TeleText.opaque.value = False
503     else:
504       config.plugins.TeleText.opaque.value = True
505     config.plugins.TeleText.opaque.save()
506     configfile.save()
507     self.opaqueValue = config.plugins.TeleText.opaque.value
508     x = array.array('B')
509     x.append(CMD_OPAQUE)
510     self.socketSend(x)
511
512   def textPressed(self):
513     if self.nav_mode != NAV_MODE_TEXT or self.catchPage or self.pageInput != 0:
514       return
515     log("text pressed")
516     self.resetVideo()
517     self.__closed()
518     self.close()
519
520   def menuPressed(self):
521     if self.nav_mode != NAV_MODE_TEXT or self.catchPage or self.pageInput != 0:
522       return
523     log("menu pressed")
524     self.__closed()
525     self.resetVideo()
526     self.session.openWithCallback(self.menuResult, TeleTextMenu)
527
528   def menuResult(self, result):
529     if result is None:
530       return
531     
532     self.nav_text_only = config.plugins.TeleText.textOnly.value
533     self.nav_config = result
534     self.nav_orig_pos   = result.value
535     self.nav_pos    = result.value
536     
537     if result == config.plugins.TeleText.pos:
538       self.nav_mode = NAV_MODE_SIZE_TEXT
539       config.plugins.TeleText.textOnly.value = True
540     elif result == config.plugins.TeleText.tip_pos:
541       self.nav_mode = NAV_MODE_SIZE_TIP_TEXT
542       config.plugins.TeleText.textOnly.value = False
543       config.plugins.TeleText.textOnly.value = SPLIT_MODE_TIP
544     self.updateLayout()
545
546   def updateLayout(self):
547     if self.nav_mode == NAV_MODE_TEXT:
548       pos = config.plugins.TeleText.pos.value
549     else:
550       pos = self.nav_pos
551     right  = pos[2]
552     bottom = pos[3]
553     mode = config.plugins.TeleText.splitting_mode.value
554
555     if config.plugins.TeleText.textOnly.value == True:
556       left  = pos[0]
557       width  = right - left
558       top    = pos[1]
559       height = bottom - top
560       self.resetVideo()
561     elif mode == SPLIT_MODE_PAT:
562       left   = dsk_width>>1
563       width  = right - (dsk_width>>1)
564       top    = pos[1]
565       height = bottom - top
566       log("splitting video")
567       l=open("/proc/stb/vmpeg/0/dst_left","w")
568       l.write("%x" % 0)
569       l.close()
570       w=open("/proc/stb/vmpeg/0/dst_width","w")
571       w.write("%x" % 360)
572       w.close()
573     elif mode == SPLIT_MODE_TAP:
574       left   = pos[0]
575       width  = (dsk_width>>1) - left
576       top    = pos[1]
577       height = bottom - top
578       log("splitting video")
579       l=open("/proc/stb/vmpeg/0/dst_left","w")
580       l.write("%x" % 360)
581       l.close()
582       w=open("/proc/stb/vmpeg/0/dst_width","w")
583       w.write("%x" % 360)
584       w.close()
585     elif mode == SPLIT_MODE_TIP:
586       if self.nav_mode == NAV_MODE_TEXT:
587         pos = config.plugins.TeleText.tip_pos.value
588       left   = pos[0]
589       width  = pos[2] - left
590       top    = pos[1]
591       height = pos[3] - top
592       self.resetVideo()
593
594     log("screen rect %s %s %s %s" % (left, top, width, height))
595     self.instance.move(ePoint(left,top))
596     self.instance.resize(eSize(*(width, height)))
597
598     self.ttx.hide()
599     self.ttx.show(self.instance)
600     self.ttx.update(0,0,492,250,self.zoom)
601
602   def resetVideo(self):
603     log("reset video")
604     l=open("/proc/stb/vmpeg/0/dst_left","w")
605     l.write("%x" % 0)
606     l.close()
607     w=open("/proc/stb/vmpeg/0/dst_width","w")
608     w.write("%x" % 720)
609     w.close()
610
611   def sendSettings(self, result = True):
612     if result:
613       # region
614       x = array.array('B')
615       x.append(CMD_REGION)
616       x.append(int(config.plugins.TeleText.region.value))
617       self.socketSend(x)
618       # Helligkeit
619       x = array.array('B')
620       x.append(CMD_SET_BRIGH)
621       x.append(config.plugins.TeleText.brightness.value<<4)
622       self.socketSend(x)
623       # Kontrast
624       x = array.array('B')
625       x.append(CMD_SET_CONTR)
626       x.append(config.plugins.TeleText.contrast.value<<4)
627       self.socketSend(x)
628       # Transparenz
629       x = array.array('B')
630       x.append(CMD_TRANSPARENCY)
631       x.append(config.plugins.TeleText.transparency.value<<4)
632       self.socketSend(x)
633       # edge cut
634       if self.edgeValue != config.plugins.TeleText.edge_cut.value:
635         self.edgeValue = config.plugins.TeleText.edge_cut.value
636         x = array.array('B')
637         x.append(CMD_EDGE_CUT)
638         self.socketSend(x)
639       # teletext level
640       x = array.array('B')
641       x.append(CMD_TEXTLEVEL)
642       x.append(int(config.plugins.TeleText.textlevel.value))
643       self.socketSend(x)
644       # opaque
645       if self.opaqueValue != config.plugins.TeleText.opaque.value:
646         self.opaqueValue = config.plugins.TeleText.opaque.value
647         x = array.array('B')
648         x.append(CMD_OPAQUE)
649         self.socketSend(x)
650
651   def helpPressed(self):
652     self.__closed()
653     self.resetVideo()
654     self.session.open(HelpMenu, self.helpList)     
655
656   def okPressed(self):
657     if self.nav_mode == NAV_MODE_TEXT:
658       if self.pageInput != 0:
659         return
660       log("ok pressed")
661       if self.catchPage:
662         x = array.array('B', (CMD_CATCHPAGE, 3, 1))
663         self.catchPage = False
664       else:
665         x = array.array('B', (CMD_CATCHPAGE, 1, 0))
666         self.catchPage = True
667         self.zoom = TeletextInterface.MODE_FULL
668       self.socketSend(x)
669     else:
670       if self.nav_mode == NAV_MODE_SIZE_TEXT:
671         config.plugins.TeleText.pos.value = self.nav_pos
672         config.plugins.TeleText.pos.save()
673       else:
674         config.plugins.TeleText.tip_pos.value = self.nav_pos
675         config.plugins.TeleText.tip_pos.save()
676       config.plugins.TeleText.textOnly.value = self.nav_text_only
677       del self.nav_text_only
678       del self.nav_config
679       del self.nav_orig_pos
680       del self.nav_pos
681       self.nav_mode = NAV_MODE_TEXT
682       self.updateLayout()
683
684   def cancelPressed(self):
685     if self.nav_mode == NAV_MODE_TEXT:
686       if self.pageInput != 0:
687         return
688       log("cancel pressed")
689       if self.catchPage:
690         x = array.array('B', (CMD_CATCHPAGE, 3, 0))
691         self.socketSend(x)
692         self.catchPage = False
693       else:
694         self.resetVideo()
695         self.__closed()
696         self.close()
697     else:
698       if self.nav_mode == NAV_MODE_SIZE_TEXT:
699         config.plugins.TeleText.pos.cancel()
700       else:
701         config.plugins.TeleText.tip_pos.cancel()
702       config.plugins.TeleText.textOnly.value = self.nav_text_only
703       del self.nav_text_only
704       del self.nav_config
705       del self.nav_orig_pos
706       del self.nav_pos
707       self.nav_mode = NAV_MODE_TEXT
708       self.updateLayout()
709
710   def serviceStarted(self):
711     log("service started")
712
713   def serviceStopped(self):
714     log("service stopped")
715     x = array.array('B', (CMD_CTL_CACHE, 0, 0, 0))
716     self.socketSend(x)
717
718   def serviceInfoChanged(self):
719     log("serviceInfoChanged")
720     service = self.session.nav.getCurrentService()
721     info = service and service.info()
722     txtpid = info and info.getInfo(iServiceInformation.sTXTPID)
723
724     self.hasText = txtpid is not None and txtpid > -1
725
726     stream = service and service.stream()
727     demux = stream and stream.getStreamingData()
728     demux = demux and demux.get("demux", -1)
729
730     log("TXT PID %s DEMUX %s" % (txtpid, demux))
731
732     if demux > -1 and self.hasText:
733       x = array.array('B', (CMD_CTL_CACHE, (txtpid & 0xFF00) >> 8, (txtpid&0xFF), demux))
734       self.socketSend(x)
735
736   def showMessages(self):
737     return config.plugins.TeleText.messages.value
738
739   # ---- for summary (lcd) ----
740
741   def createSummary(self):
742     return TeleTextSummary
743
744   def flofEnabled(self):
745     return self.flofValue
746     
747   def infoEnabled(self):
748     return self.infoValue
749
750 # ----------------------------------------
751
752 class TeleTextSummary(Screen):
753
754   def __init__(self, session, parent):
755     onPic  = resolveFilename(SCOPE_PLUGINS, "Extensions/TeleText/lcd_on.png")
756     offPic = resolveFilename(SCOPE_PLUGINS, "Extensions/TeleText/lcd_off.png")
757
758     TeleTextSummary.skin = """<screen name="TeleTextSummary" position="0,0" size="132,64">
759       <widget name="SetupTitle" position="6,4" size="120,20" font="Regular;20" halign="center"/>
760
761       <widget name="flof_off" position="24,28" size="20,20" pixmap="%s" zPosition="1"/>
762       <widget name="info_off" position="88,28" size="20,20" pixmap="%s" zPosition="1"/>
763       <widget name="flof_on"  position="24,28" size="20,20" pixmap="%s" zPosition="2"/>
764       <widget name="info_on"  position="88,28" size="20,20" pixmap="%s" zPosition="2"/>
765
766       <widget name="flof_txt" position="10,50" size="48,12" font="Regular;12" valign="center" halign="center" zPosition="1"/>
767       <widget name="info_txt" position="74,50" size="48,12" font="Regular;12" valign="center" halign="center" zPosition="1"/> 
768     </screen>""" % (offPic, offPic, onPic, onPic)
769
770     Screen.__init__(self, session, parent = parent)
771     self["SetupTitle"] = Label("TeleText")
772     self["flof_txt"] = Label("FLOF")
773     self["info_txt"] = Label("INFO")
774     self["flof_off"] = Pixmap()
775     self["info_off"] = Pixmap()
776     self["flof_on"]  = Pixmap()
777     self["info_on"]  = Pixmap()
778     self.onShow.append(self.addWatcher)
779     self.onHide.append(self.removeWatcher)
780
781   def addWatcher(self):
782     self.parent.onChangedEntry.append(self.selectionChanged)
783     self.selectionChanged()
784
785   def removeWatcher(self):
786     self.parent.onChangedEntry.remove(self.selectionChanged)
787
788   def selectionChanged(self):
789     if self.parent.flofEnabled():
790       self["flof_off"].hide()
791       self["flof_on"].show()
792     else:
793       self["flof_on"].hide()
794       self["flof_off"].show()
795
796     if self.parent.infoEnabled():
797       self["info_off"].hide()
798       self["info_on"].show()
799     else:
800       self["info_on"].hide()
801       self["info_off"].show()
802
803 # ----------------------------------------
804
805 class TeleTextMenu(ConfigListScreen, Screen):
806
807   onChangedEntry = [ ]
808   isInitialized = False
809
810   def __init__(self, session):
811     width = 492
812     height = 400
813     left = (dsk_width - width)>>1
814     top = (dsk_height - height)>>1
815     log("[menu] screen rect %s %s %s %s" % (left, top, width, height))
816     TeleTextMenu.skin = """<screen position="%d,%d" size="%d,%d" title="%s">
817         <widget name="config" position="0,0"   size="492,275" scrollbarMode="showOnDemand" zPosition="1"/>
818         <ePixmap pixmap="skin_default/div-h.png" position="0,280" zPosition="1" size="492,2" />
819         <widget name="label"  position="0,285" size="492,65" font="Regular;16" zPosition="1" halign="left" valign="top"/>
820         <ePixmap pixmap="skin_default/div-h.png" position="0,355" zPosition="1" size="492,2" />
821         <ePixmap pixmap="skin_default/buttons/red.png"    position="0,360"   zPosition="0" size="140,40" transparent="1" alphatest="on" />
822         <ePixmap pixmap="skin_default/buttons/green.png"  position="176,360" zPosition="0" size="140,40" transparent="1" alphatest="on" />
823         <ePixmap pixmap="skin_default/buttons/yellow.png" position="352,360" zPosition="0" size="140,40" transparent="1" alphatest="on" />
824         <widget render="Label" source="key_r" position="0,360"   size="140,40" zPosition="5" valign="center" halign="center" backgroundColor="red" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
825         <widget render="Label" source="key_g" position="176,360" size="140,40" zPosition="5" valign="center" halign="center" backgroundColor="red" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
826         <widget render="Label" source="key_y" position="352,360" size="140,40" zPosition="5" valign="center" halign="center" backgroundColor="red" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
827       </screen>""" % (left, top, width, height, _("TeleText settings"))
828
829     Screen.__init__(self, session)
830
831     # create config list
832     self.list = [] 
833     ConfigListScreen.__init__(self, self.list) 
834     self.createConfigList()
835
836     self["actions"] = ActionMap(["OkCancelActions", "TeleTextActions"],
837     {
838       "ok"     : self.okPressed,
839       "cancel" : self.cancelPressed,
840       "red"    : self.cancelPressed,
841       "green"  : self.okPressed,
842       "yellow" : self.resetPressed,
843       "menu"   : self.cancelPressed,
844       "text"   : self.textPressed
845     }, -2)
846     self["actions"].setEnabled(True)
847
848     self["label"] = Label("Info")
849     self["key_r"] = StaticText(_("Cancel"))
850     self["key_y"] = StaticText(_("Default"))
851     self["key_g"] = StaticText(_("OK")) 
852     self.onLayoutFinish.append(self.__layoutFinished)
853
854   def __layoutFinished(self):
855     self.isInitialized = True
856     if not self.selectionChanged in self["config"].onSelectionChanged:
857       self["config"].onSelectionChanged.append(self.selectionChanged)
858     self.selectionChanged()     
859
860   def selectionChanged(self):
861     configele = self["config"].getCurrent()[1]
862     if configele == config.plugins.TeleText.pos:
863       self["label"].setText(HELP_TEXT_POS)
864     elif configele == config.plugins.TeleText.brightness:
865       self["label"].setText(HELP_TEXT_BRIGHTNESS)
866     elif configele == config.plugins.TeleText.contrast:
867       self["label"].setText(HELP_TEXT_CONTRAST)
868     elif configele == config.plugins.TeleText.transparency:
869       self["label"].setText(HELP_TEXT_TRANSPARENCY)
870     elif configele == config.plugins.TeleText.splitting_mode:
871       self["label"].setText(HELP_TEXT_SPLITTING)
872     elif configele == config.plugins.TeleText.tip_pos:
873       self["label"].setText(HELP_TEXT_TIP_POS)
874     elif configele == config.plugins.TeleText.messages:
875       self["label"].setText(HELP_TEXT_MESSAGES)
876     elif configele == config.plugins.TeleText.debug:
877       self["label"].setText(HELP_TEXT_DEBUG)
878     elif configele == config.plugins.TeleText.edge_cut:
879       self["label"].setText(HELP_TEXT_EDGE_CUT)
880     elif configele == config.plugins.TeleText.textlevel:
881       self["label"].setText(HELP_TEXT_TEXTLEVEL)
882     elif configele == config.plugins.TeleText.region:
883       self["label"].setText(HELP_TEXT_REGION)
884
885   def createConfig(self, configele):
886     if not self.isInitialized:
887       return
888     self.createConfigList()
889
890   def createConfigList(self):
891     self.isInitialized = False
892
893     # remove notifiers
894     for x in self["config"].list:
895       x[1].clearNotifiers() 
896
897     self.list = [
898       getConfigListEntry(_("Brightness"),        config.plugins.TeleText.brightness),
899       getConfigListEntry(_("Contrast"),          config.plugins.TeleText.contrast),
900       getConfigListEntry(_("Transparency"),      config.plugins.TeleText.transparency),
901       getConfigListEntry(_("Text level"),        config.plugins.TeleText.textlevel),
902       getConfigListEntry(_("Region"),            config.plugins.TeleText.region),
903       getConfigListEntry(_("Position and size"), config.plugins.TeleText.pos),
904       getConfigListEntry(_("Display edges"),     config.plugins.TeleText.edge_cut),
905       getConfigListEntry(_("Splitting mode"),    config.plugins.TeleText.splitting_mode)
906     ]
907     if config.plugins.TeleText.splitting_mode.value == SPLIT_MODE_TIP:
908       self.list.append(getConfigListEntry("... %s" % _("Position and size"),   config.plugins.TeleText.tip_pos))
909     self.list.append(getConfigListEntry(_("Message"), config.plugins.TeleText.messages))
910     self.list.append(getConfigListEntry(_("Debug"),   config.plugins.TeleText.debug))
911
912     self["config"].list = self.list
913
914     # add notifiers (lcd, info)
915     for x in self["config"].list:
916       x[1].addNotifier(self.changedEntry)
917     # add notifiers (menu)
918     config.plugins.TeleText.splitting_mode.addNotifier(self.createConfig)
919
920     self.isInitialized = True
921
922   def resetPressed(self):
923     log("[menu] reset pressed")
924     config.plugins.TeleText.brightness.setValue(8)
925     config.plugins.TeleText.contrast.setValue(12)
926     config.plugins.TeleText.transparency.setValue(8)
927     config.plugins.TeleText.messages.setValue(True)
928     config.plugins.TeleText.edge_cut.setValue(False)
929     config.plugins.TeleText.splitting_mode.setValue(SPLIT_MODE_PAT)
930     config.plugins.TeleText.textlevel.setValue("2")
931     config.plugins.TeleText.region.setValue("16")
932     config.plugins.TeleText.debug.setValue(False)
933     config.plugins.TeleText.pos.setValue([0, 0, dsk_width, dsk_height])
934     config.plugins.TeleText.tip_pos.setValue([(dsk_width>>1)+(dsk_width>>2), (dsk_height>>1)+(dsk_height>>2), dsk_width, dsk_height])
935
936   def textPressed(self):
937     log("[menu] text pressed")
938     if self["config"].getCurrent()[1] == config.plugins.TeleText.pos:
939       self.close(config.plugins.TeleText.pos)
940     elif self["config"].getCurrent()[1] == config.plugins.TeleText.tip_pos:
941       self.close(config.plugins.TeleText.tip_pos)
942
943   def okPressed(self):
944     log("[menu] ok pressed")
945     self.checkPositionValues(config.plugins.TeleText.pos)
946     self.checkPositionValues(config.plugins.TeleText.tip_pos)
947     for x in self["config"].list:
948       x[1].save()
949     configfile.save()
950     self.close(None) 
951
952   def checkPositionValues(self, configele):
953     pos = configele.value
954     log("... old pos: %s %s %s %s" % (pos[0], pos[1], pos[2], pos[3]))
955     update = False
956     if pos[0] > pos[2]:
957       i = pos[0]
958       pos[0] = pos[2]
959       pos[2] = i
960       update = True
961     if pos[1] > pos[3]:
962       i = pos[1]
963       pos[1] = pos[3]
964       pos[3] = i
965       update = True
966     if (pos[2] - pos[0]) < MIN_W:
967       pos[2] = pos[0] + MIN_W
968       update = True
969     if (pos[3] - pos[1]) < MIN_H:
970       pos[3] = pos[1] + MIN_H
971       update = True
972     if pos[2] > dsk_width:
973       pos[0] = pos[0] + dsk_width - pos[2]
974       pos[2] = dsk_width
975       update = True
976     if pos[3] > dsk_height:
977       pos[1] = pos[1] + dsk_height - pos[3]
978       pos[3] = dsk_height
979       update = True
980     log("... new pos: %s %s %s %s" % (pos[0], pos[1], pos[2], pos[3]))
981       
982     if update:
983       configele.setValue(pos)
984
985   def cancelPressed(self):
986     log("[menu] cancel pressed")
987     confirm = False
988     for x in self["config"].list:
989       confirm = confirm or x[1].isChanged()
990     if confirm:
991       self.session.openWithCallback(self.DiscardConfirm, MessageBox, _("Discard changes?"))
992     else:
993       self.close(None) 
994
995   def DiscardConfirm(self, result):
996     if result:
997       for x in self["config"].list:
998         if x[1].isChanged():
999           x[1].cancel()
1000       self.close(None)
1001
1002   # ---- for summary (lcd) ----
1003
1004   def changedEntry(self, element=None):
1005     for x in self.onChangedEntry:
1006       x()
1007
1008   def getCurrentEntry(self):
1009     return self["config"].getCurrent()[0]
1010
1011   def getCurrentValue(self):
1012     return str(self["config"].getCurrent()[1].getText())
1013
1014   def createSummary(self):
1015     return TeleTextMenuSummary
1016
1017 # ----------------------------------------
1018
1019 class TeleTextMenuSummary(Screen):
1020   skin = """<screen name="TeleTextMenuSummary" position="0,0" size="132,64">
1021       <widget name="SetupTitle" position="6,4"  size="120,20" font="Regular;20" halign="center"/>
1022       <widget name="SetupEntry" position="6,30" size="120,12" font="Regular;12" halign="left"/>
1023       <widget name="SetupValue" position="6,48" size="120,12" font="Regular;12" halign="right"/>
1024     </screen>"""
1025
1026   def __init__(self, session, parent):
1027     Screen.__init__(self, session, parent = parent)
1028     self["SetupTitle"] = Label("TeleText")
1029     self["SetupEntry"] = Label("")
1030     self["SetupValue"] = Label("")
1031     self.onShow.append(self.addWatcher)
1032     self.onHide.append(self.removeWatcher)
1033
1034   def addWatcher(self):
1035     self.parent.onChangedEntry.append(self.selectionChanged)
1036     self.parent["config"].onSelectionChanged.append(self.selectionChanged)
1037     self.selectionChanged()
1038
1039   def removeWatcher(self):
1040     self.parent.onChangedEntry.remove(self.selectionChanged)
1041     self.parent["config"].onSelectionChanged.remove(self.selectionChanged)
1042
1043   def selectionChanged(self):
1044     self["SetupEntry"].text = self.parent.getCurrentEntry()
1045     self["SetupValue"].text = self.parent.getCurrentValue() 
1046
1047 # ----------------------------------------
1048
1049 def sessionstart(reason, session):
1050   log("----- sessionstart(%s) -----" % session)
1051   # Plugin initialisieren
1052   global ttx_screen;
1053   ttx_screen = session.instantiateDialog(TeleText)
1054
1055 def autostart(reason, **kwargs):
1056   log("autostart(%s, %s)" % (reason, kwargs))
1057   if reason == 0:
1058     pass
1059   elif reason == 1:
1060     pass
1061
1062 def mainText(session, **kwargs):
1063   global ttx_screen
1064   log("mainText")
1065   if ttx_screen.hasText:
1066     session.execDialog(ttx_screen)
1067   else:
1068     if ttx_screen.showMessages():
1069       session.open(MessageBox, _("No teletext available."), MessageBox.TYPE_INFO, timeout = 3)
1070
1071 def mainMenu(session, **kwargs):
1072   global ttx_screen
1073   log("mainMenu")
1074   session.open(TeleTextMenu)
1075
1076 def Plugins(**kwargs):
1077   log("plugins")
1078   return [
1079     PluginDescriptor(name="TeleText", description="teletext", where = PluginDescriptor.WHERE_TELETEXT, fnc=mainText),
1080     PluginDescriptor(needsRestart = False, where = PluginDescriptor.WHERE_SESSIONSTART, fnc=sessionstart),
1081     PluginDescriptor(needsRestart = False, where = PluginDescriptor.WHERE_AUTOSTART, fnc=autostart)
1082     ]
1083
1084 # EOF