Wednesday, August 22, 2012

Sending desktop notifications from scripts

Every now and then, you may find a need for sending a notification from your script.
Recently I wrote some scripts for my Thinkpad X220 (which I am going to write about too) and I needed to show notification about microphone state (enabled/disabled).

Almost every linux DE has its own notification daemon that shows notifications over DBus using org.freedesktop.Notifications (spec).

Without knowing how it works, you can use notify-send command from libnotify-bin package. Its usage is pretty straightforward:
notify-send -i "icon-file/name" -a "application_name" "Summary" "Body of message"
For almost all cases, it can serve very well. However, there is one thing that notify-send doesn't support whilst DBus specification does. 
replaces_id UINT32 The optional notification ID that this notification replaces. The server must atomically (ie with no flicker or other visual cues) replace the given notification with this one. This allows clients to effectively modify the notification while it's active.
Without it, if you call your script more than once in a short period, you'll end up with a lot of notifications on your screen. It doesn't look very good.

That means notify-send is not good enough for my needs. Little searching on google reveals that dbus-send command can be used for sending any DBus call directly. Another searching got me to ubuntuforums where one user wrote an example usage of dbus-send for sending notifications.

However, it doesn't work: dbus-send does not supports sending a{sv} type. It is DICT containing string:variant pairs.
org.freedesktop.Notifications.Notify has susssasa{sv}i signature and dbus-send can only support susssasa{ss}i.

So dbus-send wasn't an answer too. I saw a patch for notify-send on launchpad that adds support for replaces_id, but instead of using it, I decided to write my own clone of notify-send.
I could have written it using a higher-level bindings (eg. in Qt), but I wanted it to be as small as possible without unnecessary external dependencies.


Because of the requirement to make it as small as possible, language of the choice was C. It makes it possible to use direct DBus API without any additional layer.

I tried to retain arguments compatibility between notify-send and notify-desktop. The only thing that notify-desktop doesn't support is option to pass additional hints. I never used it and also don't find it useful, so I didn't bother implementing it.

The main difference is of course slightly different name and -r / --replaces-id=ID option. It does exactly what it says.

You can find it at github. Build instructions are in README.
There are also example bash functions to use in your scripts (look at doc/ directory)

No comments:

Post a Comment