xkbgrowl on Google Code

xlogo: it works

Quite some time has passed since I last updated my small growl tool. I finally cleaned up the code and uploaded all of it to a google code repository. I also fixed a few bugs: the program should no longer crash when retrieving a non existing desktop manager icon, text encoding are now done according to the spec (iso-latin-1), and more information is added to the notification text, including the name of the X11 display used by the client. For more information, have a look at https://code.google.com/p/xkbgrowl/.

screen & X11

One of the most powerful command line tools under Unix is screen. This tool lets you run a terminal emulator from within a terminal emulator. This is way more useful as it sound, it basically means you can have command-line sessions that are persistent between connections. So if you have a server, you can let the session run, even while you disconnect from the server. You can also have multiple logical terminals running in the same window, a shared information bar and of course, and abstruse configuration format. Here is the configuration I have, largely inspired by the one of a colleague. It sets control-Y to trigger screen commands, displays a bar at the bottom, with the name of the machine, the various screen sessions, the dimension of the terminal and the current time.

escape ^Yy
startup_message off
defutf8 on
info
vbell off
wrap off
hardstatus alwayslastline
hardstatus string '%{= kG}[ %{G}%H %{g}][%= %{= kw}%?%-Lw%?%{r}(%{W}%n*%f%t%?(%u)%?%{r})%{w}%?%+Lw%?%?%= %{g}][%{B} %d/%m%{W}%c %{g}]'
#!/bin/bash
set +e
for i in {10..15}
  do
  export DISPLAY="localhost:${i}.0"
  xdpyinfo -display $DISPLAY > /dev/null 2> /dev/null
  if [ $? -eq 0 ] ; then break; fi
done
message="DISPLAY: $DISPLAY"
xkbbell -display $DISPLAY "$message"

One issue with string is the definition of the X11 DISPLAY variable. As per Unix rules, this is inherited from the shell from which screen was started, so if you connect using ssh -Y it will be correct for the first ssh connection. The next time you connect, it probably will point to a non existing port. To solve this issue, I wrote a small shell script that scans for the right port, sets DISPLAY accordingly and sends a notification about it using xkbbell (as you want to inherit the DISPLAY variable, you should source this script.

#!/bin/bash
original=`basename $0`
command=${original:1}
$command "$@"
if [ $? -eq 0 ]; then
  xkbbell -v -100 -display $DISPLAY "$command $1: success"
else
  xkbbell -v 100 -display $DISPLAY "$command $1: failure"
fi

Finally I wrote a wrapper script that runs a command and then displays a status message using xkbbell once the command has finished running. The notification gets routed using xkbgrowl and displayed by Growl on my Mac OS X laptop.
The following script basically tries to run a command with the same name as itself with the first character stripped. So if you want to create a version of make that displays a notification once finished, you can write a script called xmake with the following code. For other commands, you just need to create a symbolic link (or even a hard one for the matter).

xkbgrowl

A few weeks back, I posted about a way to setup Growl to display X11 keyboard notifications. While the technique I described works, it was not really satisfying. So I decided to write a small program that would offer the same functionality (and a few others), the result is xkbgrowl.

μ-FAQ

How to I trigger a notification?
Type xkbbell "message" in a shell.
Why did you write this?
Because I wanted to
Why not use Growl network notifications?
Sending Growl network from a generic unix box requires two things: to know the address of the target Mac and that said Mac has an open network port. The first is a configuration problem, the second is a security issue. I could setup an additional ssh tunnel, but this is done automatically for the X11 connection…
Why not use XXX
There are many open source frameworks to do notifications. At a low level, Dbus seems to be the standard, at a higher level there are frameworks like Mumbles. My solution does not require to install a single thing on any Unix box, it uses software that has been there since 1995, and it uses the standard.

This small program basically connects to the X11 server and listens to X11 keyboard bell events and translates them to growl notifications. Compared to the script version, there are a few additional features:

  • No dependencies besides growl.
  • No text escaping or buffer issues
  • The volume value is translated into a Growl priority.
  • If an X11 window is associated with the event: the window name is prefixed to the notification text and the window’s icon is used as the notification icon.
  • Simple to use, just enter xkbgrowl &. The program will exit when the X11 servers quits.

The code is now hosted on google code, please go there for more information


As usual, if your computer catches fire, or any bad thing happens on your machine because you used this software, its your own fault. This code happens to work on my machine, but was not really tested on any other settings.

xkbbell & xkbevd

X11 Logo ⓒ MIT

So I started working with Eclipse on Linux. I was hoping to redefine the keyboard shortcuts to use the meta key, as I’m connecting remotely with a Mac OS X laptop and X11. I though it would be an easy task. I was wrong. In KDE applications, this just requires you to select the action, type in the new shortcut and it is done. With gtk2 this does not work. I checked with xev, the key events are the expected one: left-meta. I searched online, no useful information, just other lost users and the nagging feeling that Gnome does not honor the xmod file. Changing the keyboard settings in the gnome-control-center has no effect, this might be related to the fact I’m running a KDE desktop, but I have hardly the choice, on my virtual machine Gnome just crashes. I tried reproducing the issue on my laptop but installing gnome-terminal and launching result in the program dying horribly on launch, probably because there is no gnome desktop running, and plain X11 is way too scary. I have not solved the issue (getting rid of all things gtk would probably be the sanest solution), but digging around I stumbled on a interesting X11 extension: X Keyboard.

I have written a small binary program called xbkgrowl that does the same thing than the script presented here. It does not require any configuration file and does a few other things, link priority translation. Please check it out

In short, this extension can be used to control the lights and modifiers on the keyboard, it also gives a way of sending notifications to the X11 server. This would be something useful when I’m working on a remote Linux box, streaming back sounds is wasteful and far from stable. On my Mac, I have Growl installed so it would be really convenient to be able to trigger growl notifications. There are versions of Growl, or Growl-like project under linux, and Growl has network support, but this requires a fixed IP adresses, an open port on my Mac, and installing software or at least writing some script. But actually by using the X keyboard dæmon and an old command line you can do this using the X11 connection and without installing anything on the Linux side.

  • Install growlnotify on Mac OS X.
  • Create a configuration file xkbevd.cf with the following content:
    Bell()  shell "/usr/local/bin/growlnotify --message \"$(name)\" --appIcon X11; true "
    
  • Start the X11 server (you can just start xlogo)
  • Start the X keyboard dæmon with the following command xkbevd -cfg xkbevd.cf -bg. This will start the program in background using the configuration defined in xkbevd.cf.
  • You can now trigger a notification using the command xkbbell message, for instance xkbbell "lasers offline". This should work both locally and on remote machines.
    This only works if the X11 display on your Unix box point back to the X11 server on your Mac. You can test this by launching xlogo on the Unix box, it should display the logo on the Mac’s screen. If you have connected using ssh, make sure you selected the -Y option.

Some notes:

  • This is an old protocol (1995) which has never been seriously supported. Use at your own risk.
  • The xkbevd program, is buggy. In particular, there seems to be some issue with the memory buffer used for command substitution, no end marker is inserted, so when a long message is followed by a short one, the short command will have the last characters from the long one at its end. This is why the second command is true, which ignores all its arguments.
  • While the xkbbell command recognises many options, only the volume flag seems to be carried to the server. The volume is in the $(volume) variable, with the value of 50 added.
  • The notifications are carried over NX, but the text message is discarded.
  • There are some standard bell names defined in the header files, but any arbitrary ASCII string seems to work.
  • Instead of growl, you can also use the Mac OS X command say. In that case, the configuration file would be:
    Bell()  shell "/usr/bin/say \"$(name)\" ; true "
    
  • It is possible to define different actions for different messages, so for instance.
    Bell()  shell "/usr/local/bin/growlnotify --message \"$(name)\" --appIcon X11; true "
    Bell(Warning) shell "/usr/bin/say Warning
    

I more or less fixed the gtk issue with xmodmap, but this is really a kludge.

Growl SNMP Adapter

SNMP Notification logo

Growl is an interesting open-source project. The idea is to have one central service to handle bezel like notifications. The system has evolved and can now display notifications using different GUIs. There are now quite a few applications relying on Growl for notification, first Adium, but also Skype. There are also plugins so that newly delivered e-mails in Mail trigger such a notification.

One drawback of Growl, is that it does not really integrate with existing notification services like syslog, or SNMP traps. To remedy this, I have written a small java programs that takes incoming SNMP traps and translates them into growl notifications. The program is rather primitive, but it works. People who are interested can download a first version of the program. The tar file basically contains a jar file, a graphic file and a launch script. To use it, open a terminal and type sudo ./snmpgrowl.bash (the program needs to run as root to be able to link to a privileged port, that is 162. Once the password has been typed it, the program can be put into the background. You can test the installation by typing snmptrap -v 2c 127.0.0.1 0 1.2.3.4 1.1 s "Hello World"

If people are interested by the source code, they should send me an e-mail (the program is build using the snmp4j open source project. The program is at the moment very primitive and does little beyond transmitting the data.

Update the download link, which was broken