Linux

A quick presentation of D-BUS-based automation

Marco Fioretti explains how to use D-Bus scripting to automate and simplify various tasks by reconfiguring applications with GUI interfaces.

Software can be really, really irritating sometimes. Free Software is no exception to this rule, but has one great advantage: if you just have some patience, you can automate, or reconfigure to work as you wish, almost any activity that comes to your mind.

Please note that I'm not talking about hacking actual source code! What's great here is that, even if you are not a programmer, there is almost no limit to what you can do. As long as, of course, you are willing to invest some time in copying, pasting and tweaking -- inside script files -- text commands that are much easier to deal with than C/C++ code. Above all, this is true also for many programs with a graphical interface. You only need to know what to look for, and which questions to ask.

Enter D-BUS

D-BUS is a nice example of what I am talking about: "a simple way for applications to talk to one another [and to] launch applications and daemons on demand, when their services are needed." Using the interfaces described below, you can ask D-BUS-aware GUI programs to:

  • show the values of some variables they are using,
  • set some of those variables and
  • do something

You can do all this by typing the right commands at a prompt or (much better) saving them inside a shell script.

The practical consequence is that you can tell your computer to start and run by itself, at least partially, many GUI programs, just as if you were clicking their buttons. Even when their own graphical interfaces show no way to make that happen, and it seems all you can do is to click like there were no tomorrow. In a sense, it's like D-BUS provided a way to create and execute "macros", even for applications that, apparently, have no macro capability whatsoever.

How do I "speak" D-BUS?

On modern GNU/Linux distributions there are two ways to use D-Bus. One is graphical, the other works on the command line.

Qdbusviewer (see Figure A) shows all the D-BUS clients "connected" to D-BUS on your computer.

Figure A

Click to enlarge.

The session bus is user-specific; the system bus handles common events, e.g., insertion of USB drives or other hardware notifications. When you click on a client, the right pane displays, in a tree-like list, all the "Methods" available for that client, grouped by function. Clicking on a Method will show its current value or arguments and, in some cases, will let you modify it.

For a non-programmer, the main, if not only, value of qdbusviewer is as documentation and didactical tool. A big problem with this kind of hacking is that there is almost no documentation really aimed at end users. Qdbusviewer is the easiest way to know which Methods are available for any given D-BUS client, which values are acceptable for them, and what each value does.

Once you have that information, you can use it to write scripts based on the D-BUS command line tool, qdbus, that check or set the right Methods.

A practical example: automating screenshot captures

A useful example to show to show you what I mean is the Ksnapshot tool. Its manual says that you can look at its D-BUS interface and, respectively, all the methods to control it with these two commands:

  qdbus org.kde.ksnapshot-`pidof -s ksnapshot`
  qdbus org.kde.ksnapshot-`pidof -s ksnapshot` /KSnapshot

The second command produces a list of methods whose names correspond, as expected, to stuff you can do or set in the graphical interface of Ksnapshot:

  [marco@polaris ~]$  qdbus org.kde.ksnapshot-`pidof -s ksnapshot` /KSnapshot
  method void org.kde.ksnapshot.exit()
  method int org.kde.ksnapshot.grabMode()
  method bool org.kde.ksnapshot.save(QString filename)
  method void org.kde.ksnapshot.setGrabMode(int grab)
  method void org.kde.ksnapshot.setTime(int newTime)
  method void org.kde.ksnapshot.setURL(QString newURL)

(Note that this is only a partial output.)

However, it is both simpler and more fun to study how D-BUS can automate things via qdbuswiewer, or through this Ksnapshot control script by powtrix. Here I will show you only the central part of its code, to give you an idea of how it works:

    kstart -iconify ksnapshot && sleep 0.2
    while [ "$PID" == "" ]; do PID="$(pgrep ksnapshot)"; done
    program="org.kde.ksnapshot-${PID}"
    qdbus $program /KSnapshot setGrabMode "$1"
    qdbus $program /KSnapshot setTime 0
    qdbus $program /KSnapshot slotGrab
    sleep 8
    qdbus $program /KSnapshot setURL "${NAME}"
    qdbus $program /KSnapshot slotSave
    qdbus $program /KSnapshot exit

The first lines start ksnapshot in the background and get its process identification number ($PID). The rest of the code uses qdbus to set the Grab mode to Window, whole screen, or rectangular area, as specified by the user, and then grabs the snapshot and saves it in the file called $NAME.

That script makes it much faster to take screenshots at regular intervals, for example, as images for a tutorial you may be writing: put the code inside a loop, and forget it. If you chose the rectangular area mode, you may have to select it manually every time, but that's pretty much it.

This other script by Azziz uses the same technique to control the Spotify media player for Linux via keyboard, with custom shortcuts.

These two examples show how easy it is to control software via D-BUS once you know exactly what you would like to automate, and where to go to do it. You're welcome to link to your own examples in the comments, of course! Further information is in the D-Bus tutorial. In the meantime, I wish all you lots of fun with D-BUS scripting.

About

Marco Fioretti is a freelance writer and teacher whose work focuses on the impact of open digital technologies on education, ethics, civil rights, and environmental issues.

1 comments
sagarsiddhpura
sagarsiddhpura

This is what I was looking for. Thank you for the post.

Editor's Picks