This is an archived cached-text copy of the developerWorks article. Please consider viewing the original article at: IBM developerWorks



IBM®
Skip to main content
    Country/region [select]      Terms of use
 
 
    
     Home      Products      Services & industry solutions      Support & downloads      My IBM     
skip to main content

developerWorks  >  Open source  >

Create fancy on-screen displays with Ghosd and Perl

Let system events kick off on-screen alerts displaying text and images

developerWorks
Document options

Document options requiring JavaScript are not displayed

Sample code


Rate this page

Help us improve this content


Level: Intermediate

Nathan Harrington (harrington.nathan@gmail.com), Programmer, IBM

13 Feb 2007

Use Perl, Ghosd, and some network programming to display on-screen overlays of text and graphics based on messages from your local system and remote computers. Define custom images, font sizes, and colors to convey information integrated with your desktop.

On-screen displays for Windows® and Linux® graphical desktops have been around for years. Recent advances in frameless transparent windows for your Linux desktop has opened up another level of graphical capabilities. With anti-aliased fonts, true color, drop shadows, transparency, and image file loading, Ghosd gives you the capability for implementing the next level of on-screen displays.

A note about security
The code and techniques described in this article are an example of how to create on-screen alerts. This is designed for use on a machine running on a private network. It is not for use on a machine exposed directly to the Internet, where it is possible that a malevolent program could attempt to execute arbitrary code on the machine.

Using Perl and some custom compiled Ghosd programs, I'll show you how to implement your own event notification system. With some simple keyword matching and a client-server setup, you can receive on-screen type notifications of all your systems, remote or local.

Requirements

Hardware

Any PC manufactured after 2000 should provide plenty of horsepower for compiling and running the code. If you've got a graphical desktop, chances are good you're ahead of the game with a fast processor already at your desk.

Software

The Ghosd program requires the Pango and Cairo libraries. You'll need to have these installed for your Ghosd compilation and configuration to progress. Check Resources for the Cairo and Pango libraries, or skip ahead and install a great distribution of Linux that has them preinstalled. I recommend Vector Linux, as it has all of the libraries and eye candy preinstalled and configured for you to get up to speed with Ghosd.

Now that you have Pango and Cairo installed, you need to compile the Ghosd program itself. Once you've downloaded and extracted the Ghosd source code archive, compile it with the command ./configure && make install. After the configuration and install process has completed, check out the examples directory for some usage options with Ghosd. Ghosd is written in part as a library of functions to help your applications use the on-screen display design metaphor. As such, the provided examples are small C programs to show you the basics of how not only to use Ghosd from the command line but how to integrate it into your programs.



Back to top


Building command-line display utilities

Modifying text.c for command-line usefulness

Enter the examples directory and give the text.c program a try by issuing the command ./text. You'll see the hardcoded text appear in the lower right corner, blazing white. For our purposes, we'll want to be able to specify the color, position, and content of the text messages. Instead of building a new program, let's just modify the existing text.c program to meet our needs. If you want to skip ahead, download the completed text.c file included in the source code repository and compile it with the make command.

Add the variables below to the declaration section.


Listing 1. test.c declaration update

int   posX   = -50;
int   posY   = -50;
float red    = 1.0;
float green  = 1.0;
float blue   = 1.0;
int   ftSize = 30;
int   fadIn  = 300;
int   fadOut = 1500;
char  displayText[500] = "default message";

These are the default variables for the position, text contents, and color, font size, fade-in and fade-out speed in milliseconds, and an array to hold the display string. Next, we need to modify the display portion of the text to use the actual colors specified. In the render function, change the line cairo_set_source_rgba(cr, 1, 1, 1, 1.0); to cairo_set_source_rgba(cr, red, green, blue, 1.0);. This will enable the usage of the color values you passed in on the command line.

We need to modify the program to print a default message instead of crashing if all parameters are not included on the command line. In the main function, remove the lines below.


Listing 2. main() hardcoded display

  pango_layout_set_markup(layout,
                          "<span font_desc='Trebuchet 30'>"
                          "some sample text using <b>ghosd</b>"
                          /* "ار�~Jد" */
                          "</span>", -1);
  ghosd = ghosd_new();
  ghosd_text_set_position(ghosd, -50, -50, layout);
  ghosd_set_render(ghosd, render, layout);

  ghosd_flash(ghosd, 300, 1500);
  

After the above code has been removed, insert the error-checking and display code below.


Listing 3. main() error checking and display

  if( argc == 10 )
  { 
    posX   = atoi(argv[2]);
    posY   = atoi(argv[3]);
    red    = atoi(argv[4]);
    green  = atoi(argv[5]);
    blue   = atoi(argv[6]);
    ftSize = atoi(argv[7]);
    fadIn  = atoi(argv[8]);
    fadOt  = atoi(argv[9]);
    sprintf(displayText, "<span font_desc='Trebuchet %d'>%s</span>", ftSize, argv[1]);

  }else{
    sprintf(displayText,"<span font_desc='Trebuchet 30'>Incomplete command</span>");
  }

  pango_layout_set_markup(layout, displayText, -1 );

  ghosd = ghosd_new();
  ghosd_text_set_position(ghosd, posX, posY, layout);
  ghosd_set_render(ghosd, render, layout);

  ghosd_flash(ghosd, fadIn, fadOt);

With the simple error-checking code in place and the Pango layout updated, the text will be positioned however specified on the command line, using the specified size, color, and fading parameters. Run make to build your new text executable. Run the text Ghosd program example with a command like: ./text "red text example" -150 -150 1.0 0.1 0.1 40 500 2000. The example command will fade in the "red text example" string over 500ms in a 40pt red font at position -150,-150. The text will then fade out after 2000ms (2 seconds) on the screen.

The image example provided in the examples directory will suit our purposes just fine. Try the command ./image /usr/share/pixmaps/x264.png -x 40 -y 40 to show a simple image on your screen. The image below is an example of showing an image and some text simultaneously.


Figure 1. Ghosd example text and image
Ghosd example text and image



Back to top


An on-screen notifier using Perl and Ghosd

General strategy: Client-server strategy

The Ghosd program has the capability of displaying text and images with unlimited variations of size, color, and style. To use the capability effectively for monitoring system status, e-mail messages, and any other desired parameter, we need to preserve this variability while providing a simple interface for its usage. The system implemented below uses a client-server architecture to accept display events from local and remote machines.

The message string will be sent by a client, which is processed for keywords of information (read from a configuration file), and the appropriate output will be shown. For example, if the server receives a New e-mail from mark@developerWorks string, it will find the e-mail keyword and show a mail picture, along with the full text in the lower right-hand corner. If the message string sent by the client contains "error," the full message string will be printed in big red letters in the middle of screen.

Let's get started with the implementation to see how this will work.

Server implementation

The server needs to read the configuration file to determine how to display the text and images. It also needs to set up an infinite loop for listening to client connections on the specified port. After a connection has been established -- whether from the local or a remote machine -- the incoming messages are processed for matches to the keywords specified in the configuration file. Depending on the parameters in the configuration file, the appropriate text or image is displayed. With this overview of how the program works, let's begin at the beginning with the declarations section.


Listing 4. Declarations of osdServer.pl

#!/usr/bin/perl -w
# osdServer.pl - process incoming text events based on keyword matching and
#                display using Ghosd
use strict;
use FileHandle;
use Socket;

if( @ARGV != 1 ){ die "specify a port to listen on " }
my %osdHash = ();
my $proto    = "";
my $port     = "";
my $sockAddr = "";
my $fullCmd  = "";

Next up are the subroutines, beginning with readOsdFile, which is designed to process the osdServer.config file for the required keyword and display configurations.


Listing 4. readOsdFile subroutine

# readKeyWordFile reads type, keywords, (text/image) parameters
# text parameters:
# X coordinate, Y coordinate, red, green, blue, font size, fade In, fade Out
# image parameters:
# image filename, X coordinate, Y coordinate
# osdServer.confg format is:  type _#_ keywords _#_ osd parameters
sub readOsdFile  
{ 
  open(OSDFILE,"osdServer.config") or die "no osdServer.config file: $!";

    while(<OSDFILE>){

      # ignore comment lines
      if( !/^#/ ){
        chomp($_);
        my @arrLine = split "_#_";
        $arrLine[0] =~ s/ //g;
        $osdHash{ lc($arrLine[0]) }{ $arrLine[1] } = $arrLine[2];
      }#if not a comment line

    }#for each line in file

  close(OSDFILE);

}#readOsdFile

Once the keyword and display parameter hash has been built, we can move on to our simple keyword matching subroutine: matchWords.


Listing 5. matchWords subroutine

sub matchWords
{ 
  my $msgString = $_[0];
  my $type      = $_[1];

  # for the type specified
  for my $kwList ( keys %{ $osdHash{$type} } )
  { 
    # for each word
    for my $checkWord ( split " ", $kwList )
    { 
      $checkWord =~ s/ //g;
      if( $msgString =~ /$checkWord/i )
      { 
        if( $type eq "text" )
        { 
          $fullCmd .= qq{./text '$msgString' $osdHash{text}{$kwList} &};
        }else
        { 
          $fullCmd .= qq{./image -i $osdHash{image}{$kwList} &};
        }
      }#if matching word
    }#for each check word
  }#for each key word list

}#checkText

The matchWords subroutine will perform a simple presence check for the word specified in the osdServer.config file, then build a display command based on the type of on-screen display desired. For example, it will build a Ghosd image command if the keyword matches and the config file has specified an image to display. With our subroutines set up, we move quickly into the short main program logic.


Listing 6. Main program logic for osdServer.pl

readOsdFile();

$proto = getprotobyname('tcp');
socket(SERVER, PF_INET, SOCK_STREAM, $proto) or die "socket: $!\n";

$port     = $ARGV[0];
$sockAddr = sockaddr_in($port, INADDR_ANY);
bind(SERVER, $sockAddr) or die "bind: $!\n";

listen(SERVER, SOMAXCONN) or die "listen: $!\n";

# listen forever
while( 1 )
{
  my $acceptSock = accept(HANDLER, SERVER) or die "accept: $!\n";
  my($acceptPort, $acceptIpAddr) = sockaddr_in($acceptSock);

  autoflush HANDLER 1;
  while(my $msgString = <HANDLER>)
  {
    chomp($msgString);

    matchWords($msgString,"text");
    matchWords($msgString,"image");

    $fullCmd = `$fullCmd` unless $fullCmd eq "";
    $fullCmd = "";
  }#while handler

  close HANDLER or die "close HANDLER: $!\n";

}#while forever

The first part of the main program logic calls readOsdFile to set up the keyword matching and parameter hash. After the standard socket listening code is in place, the main loop is started to listen for new connections. Each time a connection comes in, every text and image type keyword match check specified in the config file is performed. If a match is found, the full command is appended and the full command of every display event is executed at once. This setup ensures that any dual image/text displays you have set up for a single event -- text and image on a new e-mail, for example -- displays at exactly the same time.

Configuration file

With your server code in place, you're ready to create your own configuration file for displaying text the way you want to. Here's an example configuration file to help you get started:


Listing 7. Example osdServer.config file

text _#_ email _#_ -250 -250 0.1 0.1 1.0 20 100 4300
text _#_ SYS _#_ -150 -150 0.1 1.0 0.1 30 100 4300
image _#_ SYS _#_ /usr/share/pixmaps/taskmanager.png -x -510 -y -510

Recall that the format of the osdServer.config file is type _#_ keyword _#_ ghosd parameters, where the parameters are determined by the type specified in the first field. For example, the first line specifies that if the word "email" exists anywhere in the incoming string, write the message in 20-point red letters at position -250,-250 - fading in for 100ms and fading back out after a little more than four seconds. The image line specifies the image and coordinates of display, along with the keyword "SYS." We will discuss this keyword later in an example of how to use the program to monitor log files.

Client implementation


Listing 8. osdClient.pl implementation

#!/usr/bin/perl -w
# osdClient.pl - send simple client text to server
use strict;
use IO::Socket::INET;
use POSIX qw(F_GETFL F_SETFL O_NONBLOCK);
my $sock = "";

if( $#ARGV != 2 ){ die "specify a ip, port, text string" }

eval
{
  $sock = IO::Socket::INET->new( 
    PeerAddr => $ARGV[0],
    PeerPort => $ARGV[1]) || die "can't set it up $!";

  $sock->blocking(0)
};

if( $@ =~ /socket/i )
{
  die "die in record retrieval socket setup with $@";
}

print $sock "$ARGV[2] \n";

This simple piece of code sets up a connection with the specified server on the specified port, then sends the text passed to it on the command line on to the server. There are many excellent documents and how-tos out there for detailed descriptions of Perl's networking features, see Resources for more information.

When creating these scripts (or downloading them from the source code repository), make sure you place them in the same directory as the Ghosd examples, usually ghosd-0.0.1/examples.



Back to top


Implementation and notification examples

Start the osdServer.pl program with the command is perl osdServer.pl 9090. The server program will now listen indefinitely on port 9090 for TCP connections from any host. Assuming you used the example configuration above, you can give your display setup a try with the command is perl osdClient.pl 127.0.0.1 9090 "email test". This will display the blue "email test" message on your screen.

You're now ready to go! Below are some more advanced examples to get you started.

xmms notification example

To have the currently playing song name display whenever the track is changed in xmms, follow these instructions. Go to the Preferences dialog in xmms by pressing Ctrl+P. Click the general plug-ins tab, then enable the Song Change plug-in. Click configure and add the following line:

/usr/bin/perl (fullpathTo_osdClient.pl) 127.0.0.1 9090 "%n xmms"

This will automatically send the current song title to the osdServer.pl program through the client. You'll need to add the following line to your osdServer.config file for the xmms events to be recognized correctly:

text _#_ xmms _#_ -150 -150 1.0 1.0 0.1 20 500 2300

System log notification example

Here's a one-liner that will monitor your system log for any event and send the notification on to the osdServer.pl program:

tail -n0 -f /var/log/messages |  \
perl -lane '$_=substr($_,30,50);$r=`perl osdClient.pl 127.0.0.1 9090 "$_ SYS"`'

The tail -n0 -f part says to skip to the end of the file and wait for new updates. The one-liner then sends a string to the osdServer.pl program by way of the osdClient.pl program that consists of the first 50 meaningful bytes of the log file entry. The "SYS" as seen in the example osdServer.config file is necessary to allow the keyword matching to take place for all system messages, regardless of their specific content.



Back to top


Conclusion and further examples

Share this...

digg Digg this story
del.icio.us Post to del.icio.us
Slashdot Slashdot it!

With these two more advanced examples, you should have a good grasp of how to integrate the Ghosd-enabled on-screen display server and client into your computing environment. If you want to monitor events on remote machines, simply copy the osdClient.pl program to the remote machine and run it with the server's IP address specified, instead of 127.0.0.1. Consider specifying strings to match if input is from a remote machine source. Alternatively, you can specify images to go with certain machines to allow you to instantly recognize which machine the message came from. In addition, you can use the image display feature to display custom graphics that have meaning only to the user, letting you know when e-mail has arrived without telling anyone looking at your screen.




Back to top


Download

DescriptionNameSizeDownload method
SimpleView Template Plug-inos-ghosdPerlText01.zip3KBHTTP
Information about download methods


Resources

Learn
  • Evan Martin wrote the Ghosd program.

  • Ghosd requires the Cairo libraries.

  • You'll also need Pango to compile Ghosd.

  • Linux Journal has a great guide to Network Programming with Perl.

  • Browse all the open source content on developerWorks.

  • To listen to interesting interviews and discussions for software developers, check out developerWorks' podcasts.

  • Stay current with developerWorks' technical events and webcasts.

  • Check out upcoming conferences, trade shows, webcasts, and other Events around the world that are of interest to IBM open source developers.

  • Visit the developerWorks Open source zone for extensive how-to information, tools, and project updates to help you develop with open source technologies and use them with IBM's products.

  • Visit Safari Books Online for a wealth of resources for open source technologies.

Get products and technologies
  • Innovate your next open source development project with IBM trial software, available for download or on DVD.


Discuss


About the author

Nathan Harrington is a programmer at IBM currently working with Linux and resource-locating technologies.




Rate this page


Please take a moment to complete this form to help us better serve you.



YesNoDon't know
 


 


12345
Not
useful
Extremely
useful
 


Back to top



    About IBM Privacy Contact