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