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