Control Your Linux Desktop with D-Bus
Every modern Linux desktop environment uses D-Bus, a system for allowing software applications to communicate with each other. Thanks to D-Bus, you can make your desktop work the way you want. In this article, I illustrate some of the things that are possible with D-Bus. Get ready for some desktop tweaking.
D-Bus (Desktop Bus) is an interprocess communication (IPC) system, which provides a mechanism for applications to talk to each other. The D-Bus designers built it from scratch, but were heavily influenced by KDE's DCOP (Desktop COmmunication Protocol) system. Currently, D-Bus is everywhere—KDE 4 has ditched DCOP for D-Bus, and GNOME is moving toward D-Bus instead of its own Bonobo system. So, D-Bus has become a desktop-agnostic IPC mechanism. Software that uses D-Bus seamlessly integrates with your desktop, regardless which desktop environment you use. D-Bus is part of the cross-desktop project freedesktop.org, and Red Hat is the primary contributor.
With D-Bus, every program that offers services to other programs registers itself. Other programs then can look up which services are available. A program also is able to register itself for events, which some system services do, for example, to detect hot-swapping hardware.
D-Bus does not allow direct process-to-process communication, but works by providing a “bus”. The bus dæmon routes messages between processes on a bus, and in this way, processes can speak to one or more applications at the same time. Each application can send messages to the bus or listen for events on the bus.
Usually, D-Bus creates two buses: a privileged system bus and a session bus. The system bus allows system-wide communication between processes with the right access permissions, and its main use is to deliver events from HAL (Hardware Abstraction Layer) to processes that are interested in hardware events. Some possible hardware events might be notification that a new hardware device has been added or that a printer queue has changed. The second bus, the session bus, is created when you log in, and it lets your applications communicate.
Each application using D-Bus exposes some objects, which generally map to internal GObject, C++ or Python objects. One application can send a message to a specific object in another application. You address each D-Bus object with a unique pathname, which looks like a filesystem pathname. To ensure that each application uses unique pathnames, a D-Bus object pathname generally is prefixed with the developer's domain name, such as /org/kde or /com/redhat. The Java programming language uses the same system with package names (for example, org.sun). A D-Bus path is made up of three parts: the service name, the object path and the interface (I give examples of them a bit later in this article).
So, how do you support or use D-Bus in your own application? The core API is written in C and is rather low level. It is not really designed for application programmers to use. Different programming languages and environments have binding layers built on top of this API, such as GLib, Qt, Python, Ruby, Perl and Mono. I don't go into C or GLib (GNOME's base library) programming here, but I give some examples written in script languages like Python and Ruby, as well as shell scripts.
The freedesktop.org project has an incomplete list of applications using D-Bus on its Web site, and the bus name for each application is listed there also. However, you can find the bus names yourself by using some interesting tools to help you explore D-Bus on your own system. For example, Qt has a graphical D-Bus browser called qdbusviewer (Figure 1). In Ubuntu, you can find the application in the qt4-dev-tools package. Although it's part of KDE, the application works perfectly on other desktop environments, including GNOME.
When you run qdbusviewer, it shows two tabs: Session Bus and System Bus. Within each tab, the left pane shows a list of service names. If you click on a service name, the right pane shows information about that service, such as the available methods and signals. For example, if you click on the service org.freedesktop.PowerManagement, and then click in the right pane through the hierarchy org/, freedesktop/ and PowerManagement/, you will have navigated two parts of the D-Bus path: org.freedesktop.PowerManagement in the left pane is the service name, and the org/freedesktop/PowerManagement in the right pane is the object path.
The object path has one final part in the right pane, three so-called interfaces, with a dot-separated name: org.freedesktop.DBus.Introspectable, org.freedesktop.DBus.Properties and org.freedesktop.PowerManagement. Each interface implements some methods and signals. These are the things you can interact with. Here, we're interested in the interface org.freedesktop.PowerManagement, as this one implements the concrete power management actions. When you click on it, you can see all implemented methods and signals in a list. If you click on the method Suspend, your computer suspends, and wakes up only when you press the power button.
Some methods, such as Shutdown, Reboot, Hibernate and Suspend implement actions, and other methods give you some information about the system. For example, the org.freedesktop.PowerManagement object implements some methods like GetLowBattery, GetOnBattery, CanShutdown and so on. If your system (laptop) is running on battery power but with enough battery time remaining, clicking on GetOnBattery gives a reply “Arguments: true” in the pane below, but if you click on GetLowBattery, it gives the reply “Arguments: false”.
It's worth pointing out that qdbusviewer can show only the service names that are registered at the moment. For example, if you haven't started Pidgin, the viewer won't list the Pidgin service. Take this into account when you are exploring the D-Bus services you can use on your system.
If you are more of a command-line person, you don't have to fire up qdbusviewer. The command-line application qdbus exposes the same information. If you run qdbus in a terminal, you get the list of service names available on the session bus. If you run it with the --system flag, the services known to the system bus are shown. If you want to know the different objects a service exposes, run, for example:
$ qdbus org.freedesktop.PowerManagement / /org /org/freedesktop /org/freedesktop/PowerManagement /org/freedesktop/PowerManagement/Backlight /org/freedesktop/PowerManagement/Inhibit /org/freedesktop/PowerManagement/Statistics
Now, if you want to know which interfaces the /org/freedesktop/PowerManagement object implements, use:
$ qdbus org.freedesktop.PowerManagement \ /org/freedesktop/PowerManagement
This will give the same list of methods and interfaces that you saw in qdbusviewer. For example, the line:
method bool org.freedesktop.PowerManagement.GetOnBattery()
The bool means this method returns a boolean value, which can be true or false. If the method doesn't return a value, for example, org.freedesktop.PowerManagement.Suspend(), the line lists void instead of bool.
qdbus also allows you to call these methods directly. For example, if you want to call the Suspend method, execute:
$ qdbus org.freedesktop.PowerManagement \ /org/freedesktop/PowerManagement \ org.freedesktop.PowerManagement.Suspend