Posted by Steve on Sun 18 Jun 2006 at 10:20
There are several times when you'll be writing a script, or a program, which needs to communicate with the desktop user and here we'll look at two of the more modern approaches.
On Screen Display
On-Screen display basically means that text is displayed over the top of your existing desktop - literally in your display, without a popup window of any type.
This might be familiar to you if you've used the xmms-osd-plugin plugin for XMMS.
Using the xosd-bin package it is very simple to send text to the screen:
droot@lappy:~# apt-get install xosd-bin Reading package lists... Done Building dependency tree... Done The following extra packages will be installed: libxosd2
Once installed you can show text by running the osd_cat command with some text to display:
skx@lappy:~$ echo -e "Test Message from Steve\nTesting more" | osd_cat
If all goes well you should see your message on your root window in the top-left corner of your screen.
The position of the message, and the colour/font used can both be modified. Here is what I tend use:
echo "Test" | osd_cat --font='-b&h-lucida-medium-r-normal-*-34-*-*-*-p-*-iso10646-1' \ --color=green \ --pos=top \ --align=right \ --offset=50 \ --indent=50
The advantage of the xosd-bin package is that it is very simple to create a notification message without any real programming. The downside is that the message can't be dismissed early - or be interacted with by the user.
If you want your user to be able to cancel/respond to the message then you'll need something else. Something like the notification daemon.
notification-daemon
There is a new program which is intended to become the standard notification mediator which handles the display of popups and user interaction.
root@lappy:~# apt-get install libnotify1 notification-daemon dbus
(Once installed you should probably logout + login again so that the dbus daemon is setup by your session manager.)
If you want to use the notification facilities in your code you'll need to install the libnotify-dev package which contains the appropriate header files and a shared library to link against. You will also need the GTK headers and the GLib development files. Altogether these are quite a hefty download:
apt-get install libgtk2.0-dev libglib2.0-dev libnotify-dev
Once you've installed the requirements you can compile the following sample program (actually taken from the libnotify source package):
#include <libnotify/notify.h>
#include <stdio.h>
#include <unistd.h>
int main(int argc, char * argv[] )
{
NotifyNotification *n;
notify_init("Basics");
n = notify_notification_new ("Summary",
"This is the message that we want to display",
NULL, NULL);
notify_notification_set_timeout (n, 5000); // 5 seconds
if (!notify_notification_show (n, NULL))
{
fprintf(stderr, "failed to send notification\n");
return 1;
}
g_object_unref(G_OBJECT(n));
return 0;
}
Compile it by running:
skx@lappy:~$ gcc `pkg-config --cflags gtk+-2.0`\
`pkg-config --cflags glib-2.0` \
test-basic.c -lnotify -o test-basic
Once compiled execute it by running:
skx@lappy:~$ ./test-basic
All being well an attractive notification dialog should popup and disappear after five seconds - or when you click it.
If you are interested in compiling, or testing, the system without installing the large build-dependencies you can cheat and use runtime-loading! The following code does that:
/*
* Dynamic loading + use of the libnotify library.
*
* Steve
* --
* http://www.steve.org.uk/
*/
#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>
int main( int argc, char *argv[] )
{
/* Library + notification handles */
void *handle, *n;
/* signatures of functions we're going to invoke dynamically. */
typedef void (*notify_init_t)(char *);
typedef void *(*notify_notification_new_t)( char *, char *, char *, char *);
typedef void (*notify_notification_set_timeout_t)( void *, int );
typedef void (*notify_notification_show_t)(void *, char *);
/* open the library */
handle= dlopen("libnotify.so.1", RTLD_LAZY);
if ( handle == NULL )
{
printf("Failed to open library\n" );
return 1;
}
/* Find the notify_init function and invoke it. */
notify_init_t init = (notify_init_t)dlsym(handle, "notify_init");
if ( init == NULL )
{
printf("Library function not found: notify_init\n");
dlclose( handle );
return 1;
}
init("Basics");
/* Find the notify_notification_new function, and invoke it. */
notify_notification_new_t nnn = (notify_notification_new_t)dlsym(handle, "notify_notification_new");
if ( nnn == NULL )
{
printf("Library function not found: notify_notification_new\n");
dlclose( handle );
return 1;
}
n = nnn("Test subject", "Test body with <b>bold</b>, and <i>italic</i>!", NULL, NULL);
/* Find the notify_notification_set_timeout function and invoke it. */
notify_notification_set_timeout_t nnst = (notify_notification_set_timeout_t)dlsym(handle, "notify_notification_set_timeout");
if ( nnst == NULL )
{
printf("Library function not found: notify_notification_set_timeout\n");
dlclose( handle );
return 1;
}
/* invoke function, 3 second timeout. */
nnst(n, 3000 );
/* Finally shpow the notification. */
notify_notification_show_t show = (notify_notification_show_t)dlsym(handle, "notify_notification_show");
if ( init == NULL )
{
printf("Library function not found: notify_notification_show\n");
dlclose( handle );
return 1;
}
/* invoke function, passing value of integer as a parameter */
show(n, NULL );
/* close the library and exit*/
dlclose(handle );
return 0;
}
You can compile this with:
skx@lappy:~$ gcc dynamic.c -o dynamic -ldl skx@lappy:~$ ./dynamic
This program could be easily adapted to read the message, and title, from command line arguments, but as a simple sample it has probably already done its job.
Note:
To use this program you'll still need to install the notification daemon, dbus, and etc. But you dont need to install the GTK, Glib, and LibNotify development packages - note that you probably should, this is just a simple hack which works only until the API changes.
This article can be found online at the Debian Administration website at the following bookmarkable URL:
This article is copyright 2006 Steve - please ask for permission to republish or translate.