using d-bus: an example


In the previous entry, I mentioned Emacs version 23. This time, let's see what we can do with one of its new features: D-Bus-support. As you might know, D-Bus is an IPC system used on Linux/Unix to communicate between applications; it's a kind-of successor to systems like Bonobo (Gnome) and KParts (KDE). With support for D-Bus in Emacs, it's easy to control other applications. More and more programs are providing D-Bus interfaces.

As a semi-useful example of that, let's look at using D-Bus to control the Tomboy Note Taker application. Tomboy takes a novel approach (at least for me) at note taking -- your notes are connected like a wiki. Tomboy was originally designed and written by Alex Graveley, who has a talent for coming up with interesting ideas, and then turning them into software. Anyhow, I only use Tomboy as example of the use of D-Bus from emacs; there are many other interesting programs controllable through D-Bus.

Note, I won't discuss the details of D-Bus itself here; there's a lot of good material available already. Specifically, for some more background on using D-Bus with emacs, I can recommend the documentation (info-page) that comes with Emacs-23.

Back to Tomboy. First, let's make it easy to call Tomboy. It obviously assumes you have Tomboy installed, but it does not have to be running. First, a helper function that uses the new dbus-call-method-function, sets the service, path and interface names for Tomboy; this way, we don't have to specify them for each call:

(require 'dbus)
(defun djcb-call-tomboy (method &rest args)
"call the tomboy method METHOD with ARGS over dbus"
(apply 'dbus-call-method
:session ; use the session (not system) bus
"org.gnome.Tomboy" ; service name
"/org/gnome/Tomboy/RemoteControl" ; path name
"org.gnome.Tomboy.RemoteControl" ; interface name
method args))

Then, djcb-tomboy-create-note-region creates a new note from the region (selection) use CreateNamedNote and SetNoteContents; it even does some rudimentary error checking:

(defun djcb-tomboy-create-note-region (b e name)
"Create a new note with in the Tomboy notetaker from region"
(interactive "r\nsName for new Tomboy note:")
(let ((note-uri (djcb-call-tomboy "CreateNamedNote" name)))
(if (and note-uri (> (length note-uri) 0))
(djcb-call-tomboy "SetNoteContents" note-uri
(concat name "\n" (buffer-substring b e)))
(message "hmmm... it did not work. maybe try a different name"))))

With djcb-tomboy-insert-note-contents we can insert the contents of some tomboy note into the current buffer, using FindNote/GetNoteContents There's auto-completion available for the name of the note, using ListAllNotes:
(defun djcb-tomboy-insert-note-contents (name)
"Insert Tomboy note with NAME"
(interactive
(list (let ((lst))
(dolist (uri (djcb-call-tomboy "ListAllNotes"))
(add-to-list 'lst (djcb-call-tomboy "GetNoteTitle" uri)))
(completing-read "Name of Tomboy Note:" lst))))
(let ((note-uri (djcb-call-tomboy "FindNote" name)))
(when note-uri
(insert (djcb-call-tomboy "GetNoteContents" note-uri)))))

So, easy enough to do, even for an Elisp novice like myself. Again, this is more to show the use of dbus from emacs than about Tomboy itself -- but it is somewhat useful. I'm actually not using Tomboy so much anymore - org-mode better fits my emacs-centric workflow. But Tomboy has some very interesting plugins which might be nice for org-mode as well.

As I said before, Tomboy is only an example here -- there are many other D-Bus services available ('dbus-list-activatable-names') And D-Bus services are introspectable - you can search through them, and retrieve information about the interfaces they provide, as well as the methods and signatures. Again, the Emacs D-Bus infopages are quite useful.

No comments:

Post a Comment

Followers

Popular Posts