The Display Text action displays an arbitrary text on the LCD or VFD display. It acquires the display first, if necessary (see action Acquire Display action for details).
The action supports four different modes, depending on the use case:
| Use case | Example | Mode | Method | |
| 1 | Display static text | After system startup or resume, you want to display "Welcome to my home cinema!" | Simple, static text mode | Configure Display Text action through the GUI configuration dialog |
| 2 | Display dynamic text with variables | You store the current volume in a variable eg.globals.Volume. Your display shall display this value, even when it changes. | Simple, variable text mode | Configure Display Text action through the GUI configuration dialog, passing variables. |
| 3 | Display dynamic text, event triggered | Your favorite music player creates EG events (for example 'PlaybackStart' and 'PlaybackStop') when it starts/stops playing a song. You want to display the current song title or album info on the VFD or LCD screen. | Script mode | Call the DisplayText action in a EG Python Script action and pass it variables for the text to display. |
| 4 | Display dynamic text, periodically updated, not event triggered | You want to display dynamic information which requires periodic updates and for which you don't get events in EG, like a clock, weather info, CPU temperature, e-mail status etc. | User callback mode | In an EG Python Script, create a user callback function and pass it to the DisplayText action. DisplayText calls this function periodically. |
The simple, static text mode is what is provided through this GUI dialog: You can display an arbitrary, static text on the iMON VFD or LCD display by calling this action, 'out of the box'. There are a lot of nice options to control the scroll mode, scroll speed and auto clear. Just play around with them to learn how they work.
Before we discuss the script mode, let's have a look at Display Priorities, another concept of this plugin. They are easy to understand.
Imagine a stack of written papers. You can only see and read the top sheet of this stack, unless you remove it, then you see the next lower one. The 'Display Text' action works the same: It can handle an arbitrary number of display texts, but only the one with the highest display priority (i.e. the one with the lowest number) is actually displayed. As soon as it gets cleared, the next message with the next lower priority is being displayed.
You can add (and clear) messages at any time with any priority. If a new message has top priority, it is immediately displayed, if it has a lower priority, it waits until the higher priority messages are cleared. Just if you add two messages with the same priority (let's say you add msg1 with prio=3 and msg2 with prio=3), the latter one replaces the first one.
In a real-life configuration, you could use display priorities as follows:
| Priority | Usage | Meaning |
| 1 | Keypress | Display the name of the pressed key of the remote control during 1 second, then let it disappear again (see autoclear options) |
| 3 | DVBViewer Recordings | While DVBViewer is recording, display recording information (channel, show, duration etc.) on the display |
| 5 | DVBViewer Playback or Live TV | During normal live TV or playback of recordings information (channel, show, duration etc.) is shown. |
| 20 | Clock | If nothing else happens, display a date-time clock on the display. |
For most real-life situations the static text mode is not sufficient, because you want to display dynamic, real-life information on the display, like the song title or album information of what your favorite player currently plays or the status of an ongoing DVB recording. Sometimes such requirements can be achieved by the previously discussed dynamic text mode, but not always. In such cases the script mode comes into play.
One thing has to be said in advance: you need little Python knowledge to achieve this, or at least you are not frightened to learn it ;) It's not as difficult as it sounds in this documentation (it's my flaw to explain things too complicate ;))
OK, let's start. At the beginning, you need an EG event, like 'Play' or 'StartRecording' or similar. Such events are generated by other EventGhost Plugins like the VLC plugin or the DVBViewer plugin.
Triggered by such an event, you call an EventGhost Python Script, gather all information you want to display and call the DisplayText action with that information.
Here's an example of displaying information about what is currently shown in DVBViewer:
# Basic initialization
line1, line2 = '', ''
# Step 1: Get the data from DVBViewer and format it for the iMON display
data = eg.plugins.DVBViewer.GetCurrentShowDetails()
if data is not None and len(data) > 0:
line1 = '[' + data['channel'] + '] ' + data['title']
line2 = data['starttime'] + ' - ' + data['endtime']
# Step 2: Display the data on the screen
eg.plugins.iMON_Display.DisplayText(
msgPriority=5,
line1=line1,
line2=line2
)
In the previous chapter we saw how to display dynamic text in the script mode, initially started by an event. But what if you don't have an event as starting point but your information is dynamically changing over the time and requires periodic updates? What if you want to display a clock (along with other information)? Maybe you could achieve that somehow with the script mode - but your configuration would probably end in a complicated monster.
With the user callback mode there exists a much more elegant way. The rest of this chapter focuses on this mode.
That's the trick: "Don't call us, we call you" ;) With this powerful concept you're able to bring almost every desired text on the screen.
Here's the minimal code you have to put into an EG Python Script action:
from time import localtime, strftime
# Step 1: Define the callback function. (Reduced to the bare minimum for this example)
# The callback function must return two strings (they can be empty), regardless of LCD or VFD display.
def MyClockCallback( displayType, msgPriority, userCallbackObj ):
line1 = strftime( "%H:%M:%S", localtime() )
line2 = ''
print "MyClockCallback called. Going to display '" + line1 + "'" # just for debug purposes. You can safely delete this line
return line1, line2
# Step 2: Call the 'DisplayText' plugin action
# Pass the previously defined callback function.
# The callback function will be called every 'userCallbackFreqInSec' seconds.
eg.plugins.iMON_Display.DisplayText(
userCallbackFunc=MyClockCallback, # that's the trick: pass the callback into the action
userCallbackFreqInSec=1.0, # how often the callback is called
)
Run this action script once... and your iMON display starts displaying a clock, second by second... :)
One could even more shrink this code (I didn't do it to keep it better readable). With not more than four (effective) lines of code you have already a running clock on your iMON display.
Let's dive a bit deeper into the details...
def UniqueCallbackFunctionName( displayType, msgPriority, userCallbackObj ):
return str( line1 ), str( line2 )
| Name | Type | Description |
| UniqueCallbackFunctionName | Function | The name of the callback function is arbitrary - as long as it is unique within your configuration! |
| displayType | String | Input parameter; indicates the current display type. It is either 'LCD' or 'VFD'. |
| msgPriority | Integer | Input parameter; indicates the message priority. |
| userCallbackObj | Object | In-Out parameter; an optional, arbitrary object for
user data,
will be passed around with every callback function call. It allows the
programmer to cache data and to get it back with the next cycle. The userCallbackObj must be defined and passed into the DisplayText action; see description of DisplayText() parameters below for details. |
| return str( line1 ), str( line2 ) | String, String | The function must return two strings, regardless if VFD or LCD display. On VFD displays, they represent the two display lines. On LCD displays, the two strings are simply concatenated. The strings can be empty, of course. |
When working in script mode or user callback mode, you have to call the DisplayText action directly from a script. This section describes the parameters of the action.
Notes
| Name | Type | Default | Description |
| msgPriority | Positive integer | 100 | The display priority of the message.
The rules are:
|
| line1, line2 | String | (empty String) | The upper and lower line on a VFD screen.
Or the beginning and end of display text on a LCD screen. Supports variables and expressions with the following syntax: {valid_python_expression} |
| scrollMode | Positive integer | 1 | Controls how the text is scrolled over the screen.
Supported values:
|
| scrollSpeed | Positive decimal number | 8.0 chars/sec | Defines the scroll speed in characters per second |
| scrollWaitSec | Positive decimal number | 1.0 sec | Only applies for scrollMode = 2 -
SCROLL_MODE_STOP_SCROLL_STOP: Defines the wait time in seconds at the beginning and at the end. |
| maxScrollLoops | Positive integer or -1 | -1 | maxScrollLoops > 0: The number of scroll loops to be performed. After that the message stands still. maxScrollLoops = -1: |
| autoClearAfterSec | Positive decimal number or -1 | -1 | autoClearAfterSec > 0: Defines the autoClear countdown time. After this time, the message is automatically cleared. autoClearAfterSec = -1: |
| autoClearTimeAbsolute | Boolean | True | Only applies if autoClearAfterSec > 0.
True: False: |
| autoClearAfterLoops | Positive integer or -1 | -1 | autoClearAfterLoops > 0: Defines the number of scroll loops after which the message is automatically cleared. autoClearAfterLoops = -1: Mutually exclusive to 'autoClearAfterSec' |
| effects | 0 or 1 | 0 | Defines additional display effects.
effects = 0: effects = 1: (more effects to come maybe in a future release) |
| userCallbackFunc | Function reference or None | None | Points to the user callback function (if any). See separate chapter for more details. |
| userCallbackFreqInSec | Positive decimal number | 60.0 sec | Defines the frequency in seconds of the user callback calls (i.e. how often the user callback function is called). |
| userCallbackObj | Object or None | None | An arbitrary data object which is passed into the
callback function.
Allows to implement a data cache between callback calls etc. In most cases a Python data dictionnary is the most convenient object type. See below for an example on how to define and use it. |
Tired of all this theoretical stuff? - OK, let's practice again, let's demonstrate a full-fledged callback example!
This example makes use of the DVBViewer plugin - however, it's just an example on how to get data from an external source in order to display it on the screen.
from time import time, strftime
from datetime import datetime as dt
# Step 0 (optional): Display priorities have been defined outside this script like this:
eg.globals.DISP_PRIO_RECORDINGS = 3
# Step 1: Define the callback function.
def MyRecCallback(displayType, msgPriority, userCallbackObj):
line1, line2, remaining = '', '', ''
try:
if msgPriority == eg.globals.DISP_PRIO_RECORDINGS:
# get attributes from the user callback object as passed
data = userCallbackObj['lastdata']
lastcall = userCallbackObj['lastcall']
now = time()
if (now > lastcall + 30.0 or data is None):
# Optimization: an expensive function is only called twice a minute
data = eg.plugins.DVBViewer.GetTimerDetails(
active=True,
enabled=True,
allRecordings=True,
enableDVBViewer = eg.plugins.DVBViewer.IsConnected(),
enableDVBService = True,
updateDVBService = False
)
#print data
# intermediate store for some user data, we get it back again with the next callback
userCallbackObj['lastcall'] = now
userCallbackObj['lastdata'] = data
if data is not None:
success = data[0]
if success and len(data[1]) > 0:
timerlist = data[1]
line1, i = '', 0
for timer in timerlist:
if i > 0:
line1 += ' '
i += 1
line1 += '[REC] ' + timer['description'] + ' (' + timer['channelName'] + ') ' + timer['startTime'] + ' - ' + timer['endTime']
endDateTime = dt.fromtimestamp( float( timer['endDateTime'] ) )
delta = endDateTime - dt.now()
totalSecs = delta.days * 24 * 60 * 60 + delta.seconds
hh, remainder = divmod( int( totalSecs ), 3600 )
mm, ss = divmod( remainder, 60 )
d = { 'H': hh, 'M': mm, 'S': ss }
remaining = '-%(H)02d:%(M)02d' % d # :)
currTimeStr = strftime("%H:%M:%S")
line2 = currTimeStr + ' ' + remaining
print 'MyRecCallback', line1, line2
except Exception, exc:
print unicode(exc)
return line1, line2
if True or eg.plugins.DVBViewer.IsRecording(
enableDVBViewer = eg.plugins.DVBViewer.IsConnected(),
enableDVBService = True,
updateDVBService = False,
):
# Step 2a (optional): Define a user data callback object
myCallbackObj = { 'lastcall': -1, 'lastdata': None }
# Step 2b (optional): Prefetch the data in order to start with a fully initialized screen
# Prefetching makes changes between messages smoother.
line1, line2 = MyRecCallback( 'None', eg.globals.DISP_PRIO_RECORDINGS, myCallbackObj )
# Step 3: Call the 'DisplayText' action
# See the 'Simple Clock' example for details
eg.plugins.iMON_Display.DisplayText(
msgPriority=eg.globals.DISP_PRIO_RECORDINGS,
line1=line1,
line2=line2,
scrollSpeed=8.0, # chars per second
scrollMode=2, # mode STOP_SCROLL_STOP
scrollWaitSec=1.0, # standstill time at the beginning and the end
maxScrollLoops=-1, # loop infinite
userCallbackFunc=MyRecCallback, # That's the trick! The callback function is passed into the action.
userCallbackObj=myCallbackObj, # You can pass any object back into the callback function
userCallbackFreqInSec=1.0 # How frequent the callback function is called
)
else:
eg.plugins.iMON_Display.ClearText(msgPriority=eg.globals.DISP_PRIO_RECORDINGS)