Since the Gnome folk and the Growl folk never got around to agreeing on the same kind of desktop notifications or how to exchange them over a network, I finally decided to roll my own after a year or so of not having a more or less permanent Linux box.
Basically I sat down one day and hacked a Python daemon in 15 minutes or so that listens for Growl notifications and maps them to D-Bus for display on any recent Gnome system. This allows me to get desktop notifications when my router goes down or my server feels lonely regardless of the platform I'm using.
The code below is fairly "dumb" and makes no attempt at handling Growl application registration, priorities or any niceties, but it works fine for me.
I have removed the calls to PicoRendezvous that allow my local Growl relay (which listens for notifications from my machines out on the Internet and relays them to the LAN) to find all Growl-enabled machines, but this will work fine by itself (provided you also get regrowl.py, of course).
A Windows variant of this is forthcoming - in a year or so.
#!/usr/bin/env python
"""Growl 0.6 DBUS Glue"""
__version__ = "0.1"
__author__ = "Rui Carmo (http://the.taoofmac.com)"
__copyright__ = "(C) 2006 Rui Carmo. Code under BSD License."
import sys, os
import dbus
import dbus.glib
import gobject
from regrowl import GrowlPacket
from netgrowl import *
from SocketServer import *
class GrowlListener(UDPServer):
"""Growl Notification Listener"""
allow_reuse_address = True
def __init__(self, inpassword = None, outpassword = None):
"""Initializes the relay and launches the resolver thread"""
self.inpassword = inpassword
self.outpassword = outpassword
bus = dbus.SessionBus()
bus.get_object("org.freedesktop.DBus","/org/freedesktop/DBus")
notify_service = bus.get_object('org.freedesktop.Notifications', '/org/freedesktop/Notifications')
self.interface = dbus.Interface(notify_service, 'org.freedesktop.Notifications')
UDPServer.__init__(self,('localhost', GROWL_UDP_PORT), _RequestHandler)
# end def
def server_close(self):
self.resolver.shutdown()
# end def
# end class
class _RequestHandler(DatagramRequestHandler):
"""Processes and each incoming notification packet"""
def handle(self):
"""Handles each request"""
p = GrowlPacket(self.rfile.read(), self.server.inpassword,self.server.outpassword)
if p.type() == 'NOTIFY':
notification,title,description,app = p.info()
self.server.interface.Notify(app,0,'/usr/share/icons/gnome/scalable/categories/stock_internet.svg',title,notification,[],{},-1)
if __name__ == "__main__":
r = GrowlListener('password','password')
try:
r.serve_forever()
except KeyboardInterrupt:
r.server_close()