Introduction to D-Bus
From CodeCodex
D-Bus is the high-level interprocess communication protocol endorsed by FreeDesktop.Org. The protocol specification is here.
Contents |
[edit] Python
Documention for the Python D-Bus API can be found here.
[edit] Finding Out What’s On The Bus
The following list_bus script, when passed an argument of 0, will list the names on the system bus, while passing an argument of 1 will make it list the names on the session bus.
import sys
import dbus
if len(sys.argv) != 2 :
raise RuntimeError("need one arg specifying bus to list, 0 for system bus, 1 for session bus")
#end if
the_bus = (dbus.SystemBus, dbus.SessionBus)[int(sys.argv[1])]()
for name in the_bus.list_names() :
print(name)
#end for
On my Debian system with KDE 4.3,
list_bus 0
produces output like this:
org.freedesktop.DBus :1.7 :1.8 :1.9 :1.171 :1.260 org.freedesktop.NetworkManagerUserSettings :1.150 org.freedesktop.PolicyKit1 :1.20 ... (etc) ...
while
list_bus 1
produces output like this:
org.freedesktop.DBus org.freedesktop.PowerManagement :1.7 :1.8 org.kde.kded org.kde.NepomukServer org.kde.korgac org.kde.nepomuk.services.nepomukfilewatch org.kde.klipper org.kde.kwalletd org.kde.krunner org.kde.NotificationItemWatcher ... (etc) ...
[edit] Finding Out What Things Do
If you’ve read the specs, you’ll see that actually communicating with apps over D-Bus is quite an involved process: you have to specify a bus name to communicate with a particular application, an object path to some object supported by that bus name, a method name to call, and an interface name which includes that method. Luckily, if the method name is unique among all interfaces supported by that object you can leave out the interface name.
One thing that helps you figure out how to call things is you can usually ask the application itself, via D-Bus, what its supported objects, interfaces and methods are, if the application supports introspection.
The following introspect script takes three command-line arguments, the first being 0 or 1 to specify the system or session bus respectively (as with list_bus above), the second being the bus name and the third being the object path, and returns the result of introspecting that object:
import dbus
import sys
if len(sys.argv) != 4 :
raise RuntimeError("need three args, the bus spec, the bus name and object path to introspect")
#end if
the_bus = (dbus.SystemBus, dbus.SessionBus)[int(sys.argv[1])]()
the_bus_name = sys.argv[2]
the_path = sys.argv[3]
sys.stdout.write \
(
dbus.Interface
(
the_bus.get_object(the_bus_name, the_path),
dbus_interface = "org.freedesktop.DBus.Introspectable"
).Introspect()
)
For the bus name, pass any of the names returned by list_bus, and for the object name, you can start with “/” for the root object.
For example, the call
introspect 1 org.kde.screensaver /
returns
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.freedesktop.DBus.Introspectable">
<method name="Introspect">
<arg name="xml_data" type="s" direction="out"/>
</method>
</interface>
<node name="App"/>
<node name="KBookmarkManager"/>
<node name="KIO"/>
<node name="MainApplication"/>
<node name="ManagerIface_contact"/>
<node name="ScreenSaver"/>
</node>
Notice that child node called ScreenSaver? What’s in there?
ldo@theon:dbus_try> introspect 1 org.kde.screensaver /ScreenSaver
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.freedesktop.ScreenSaver" >
<signal name="ActiveChanged" >
<arg type="b" />
</signal>
<method name="Lock" />
<method name="SimulateUserActivity" />
<method name="GetActive" >
<arg direction="out" type="b" />
</method>
<method name="GetActiveTime" >
<arg direction="out" type="u" name="seconds" />
</method>
<method name="GetSessionIdleTime" >
<arg direction="out" type="u" name="seconds" />
</method>
<method name="SetActive" >
<arg direction="out" type="b" />
<arg direction="in" type="b" name="e" />
</method>
... rest omitted ...
</interface>
</node>
See that SetActive method call? Could that be what activates the screen saver?
[edit] Doing Something
Let’s try it:
import dbus
import time
screensaver = dbus.Interface \
(
dbus.SessionBus().get_object("org.kde.screensaver", "/ScreenSaver"),
dbus_interface = "org.freedesktop.ScreenSaver"
)
screensaver.SetActive(True)
time.sleep(5)
screensaver.SetActive(False)
If you run this script and don’t touch the mouse or keyboard, it should activate the screen saver for 5 seconds, then turn it off again.

