Hack 26. Never Miss Another Reminder
Flash your reminders on your desktop on top of any applications you are running.
Did you know you can display pop-up messages on top of X Windows, even if you're using multiple virtual desktops? This trick can come in handy when a pop-up dialog box or messages in a terminal window simply aren't sufficient to get your attention. And it can be fun, too. This hack explores the power of X11 On-Screen Display (XOSD), and then uses it to set reminders that will pop up on-screen at the preset time.
XOSD allows you to print messages, symbols, and even progress bars directly on-screen, on top of anything else you have displayed on your desktop. Think of it as the equivalent of the volume control meter that pops up on many televisions when you adjust the volume.
Use your distribution's preferred installation method to install XOSD. The package name usually includes the term XOSD. If you have yum set up properly, you can log in as root and install it on Fedora Core (and some other RPM-based Linux distributions) with this command:
# yum install xosd
On Debian or RPM-based distributions that support apt-get, install it with this command:
# apt-get install xosd-bin
On Gentoo, install it with this:
# emerge xosd
The distinct advantage of using XOSD is that it is often more likely to get your attention than any other alert technique. That's because the message appears on every virtual desktop, and it appears on top of any applications you are using. You can try out the XOSD program, osd_cat, with a simple command, such as the following:
$ echo "Hello there, this is osd_cat speaking." | osd_cat
You should see the message appear in tiny red text in the upper-left corner of the screen. It's so tiny, in fact, that it's hardly useful. Don't worry; you can do something about that. As long as you see the text (or something red that looks like text) you know osd_cat is working.
4.6.1. The Way You Like It
You can add several customization switches to tune how the osd_cat command presents text on the screen. The first thing you want to do is increase the text size. Use the -f switch followed by a font definition to make osd_cat use the font you prefer.
Font definitions, such as the ones used by osd_cat, can appear intimidating because they contain so much information littered with dashes and asterisks. Each part of the definition says something about the type of font, the point size, whether the font is bold, etc. It's probably safe to stick with the definitions listed here, but if you want to play with various font definitions, run the program xfontsel. This program lets you play with the various parameters that make up a font definition while showing the results in the window. When you come up with a combination you like, you can click the Select button, which will copy the full definition onto the clipboard and let you paste it into your script or program.
If you want a big eye-catching font, you'll probably want to use the following font definition, which is available in almost every Linux distribution:
If you have the Microsoft TrueType fonts installed [Hack #25], you can get a much broader range of font sizes at the cost of speed. The larger you make the font, the longer it takes for osd_cat to render the message. Here's one example:
"-microsoft-comic sans ms-*-*-*-*-48-*-*-*-*-*-*-*"
You can get some fonts to display text larger than 48 points, but it might take several seconds before you see the text on your screen.
Let's try the osd_cat test again, this time with a font definition:
$ echo "Hello there, this is osd_cat speaking." | osd_cat -f "-adobe-helvetica-bold-r-normal-*-*-240-*-*-p-*-*-*"
If everything works properly, you should see the message in much larger text.
You can use the -c switch to change the color of the text. You can use any color name defined in the /usr/X11R6/lib/X11/rgb.txt file, but unless you're really picky, it's safe to stick with basic color names, such as blue, green, yellow, cyan, white, black, and magenta. If you really want to branch out into colors, such as PapayaWhip, however, be my guest.
Green is typical of television on-screen displays, so see if it looks good for XOSD:
$ echo "Hello there, this is osd_cat speaking." | osd_cat_-c green \ -f "-adobe-helvetica-bold-r-normal-*-*-240-*-*-p-*-*-*"
If you want to get fancy, present the text with a bit of a shadow. Of course, if the message displays on a dark background, you probably won't see the shadow. Add the -s 2 switch to create a 2-pixel shadow for the message:
$ echo "Hello there, this is osd_cat speaking." | osd_cat -c green -s 2 \ -f "-adobe-helvetica-bold-r-normal-*-*-240-*-*-p-*-*-*"
Now position the text in the middle of the screen with the -p middle switch (you can choose top or bottom, if you prefer). You might see the message appear at the top of the screen for a moment, after which it shifts to the middle of the screen. This is an occasional idiosyncrasy of osd_cat that will probably be fixed as it matures. Finally, you can make the message display on the screen for longer than the default 5 seconds. Add the -d 60 switch to tell osd_cat to leave the message on the screen for 60 seconds:
$ echo "Hello there, this is osd_cat speaking." | osd_cat -c green -s 2 -p middle -d 60 -f "-*-helvetica-*-*-*-*-34-*-*-*-*-*-*-*"
A number of other switches are also available, such as a switch to indent the text. Browse the manpage for osd_cat for a list of the available customization switches.
4.6.2. Scripting the Attention-Getting Reminder
Now that you know what XOSD can do, you can put it to work by writing a script that will cause reminders to flash on the screen at the appointed time. In addition to osd_cat, you also need the at program installed for this script to work, and you must have the atd daemon running. Many Linux distributions install at and atd, and run the daemon by default. If yours does not, you have to follow the procedure for your particular distribution to install at and atd, and make sure atd starts when you boot the computer.
Now, on to the script itself. Log in as root or use sudo to fire up your favorite editor, create the file /usr/local/bin/remindme, and type in the bash script from Example 4-1 or fetch the script from O'Reilly's Examples web site for this book.
Example 4-1. remindme bash script
#!/bin/bash # figure out which display we're currently using HOST="$(xrdb -symbols | grep SERVERHOST | cut -d= -f2)" DISPLAYNUM="$(xrdb -symbols | grep DISPLAY_NUM | cut -d= -f2)" THISDISPLAY=$HOST:$DISPLAYNUM.0 # check to see if the reminders directory exists in the home directory # if not, then create the directory if [ ! -e ~/reminders ] ; then mkdir ~/reminders fi unique=`date +%F-%H-%M-%S` reminder="reminders/reminder-"$unique # Now output the reminder script echo '#!/bin/bash' > ~/$reminder echo -n 'export DISPLAY=' >> ~/$reminder echo $THISDISPLAY >> ~/$reminder echo "echo \"$2 today\" | osd_cat -s 2 -c green -p middle \ -f -adobe-helvetica-bold-r-normal-*-*-240-*-*-p-*-*-* -d 60" >> ~/$reminder # Make the reminder script executable chmod +x ~/$reminder # Schedule it to run at $1 -f ~/$reminder
Save your work, and change the file to be executable with this command:
$ sudo chmod +x /usr/local/bin/remindme
Do you need to set a quick reminder to call your boss at 2:00 p.m.? Simply type the following command:
$ remindme 2:00pm "Call your boss now."
From this command the bash script creates a separate reminder script and schedules it to run at 2:00 p.m. The script it creates will put the message on the screen using on-screen display. That means you won't be able to miss the message, because it will appear on every virtual desktop at the same time.
Here's how it works. The first part of the script determines which X Windows display you are using. Then it adds a line to the reminder file that exports the discovered display setting. The osd_cat program does not get that information from the environment, so it must be specified in the script. You can't depend on the user always being on the default display of :0.0, which is why the script has to determine the current display by querying the system with the xrdb command.
The next part of the bash script creates a unique filename based on the current time. Then it creates the first line of the bash script (#!/bin/bash) and writes it to the reminder file that will run at the proper time.
Next, it adds the on-screen display command, which substitutes "Call your boss now" for the second argument, $2. It makes the reminder script executable, and finally, it schedules the computer to run your reminder program with the at command, which uses the time at which you typed the command as your first argument. The time argument is flexible, by the way. You can type the time as 2:00PM, 2pm, or even 14:00. The script adds today for you, although if you are ambitious, you can rewrite the script to let you create reminders for specific dates in the future.
If you look carefully at the script, you can see that it stores files as something such as ~/reminders/reminder-2004-10-04-05-07-39. Note that the symbol ~ refers to your home directory, so it is storing all the reminders in the reminders subdirectory just below your home directory. If you like this script and use it often, this directory will fill up with those temporary reminder script files. They don't take up much space, so that shouldn't be much of a concern. But if you want to clean out old reminders, you can do so by checking the filenames to see how old they are. Each reminder script includes the year, month, day, hour, minute, and second as part of the filename. This makes it easy to identify expired reminders and delete them.