KDE-programma's met D-Bus besturen vanaf de commandoprompt
Tagged:  •    •    •    •    •  

Een beetje als vervolg op m'n vorige artikel wordt in dit artikel uitgelegd hoe je met KDE-programma's kan interacteren vanaf de commandoprompt. Dit gaat met behulp van D-Bus en we gebruiken hiervoor het commando qdbus. Hiermee kan je bijvoorbeeld de titel van het huidige nummer in Amarok opvragen, of kan je jezelf op afwezig zetten in Kopete.

D-Bus

Eerst zullen we eens naar D-Bus kijken. D-Bus is een mechanisme waarmee verschillende programma's (processen) met elkaar kunnen communiceren. Je kan het zien als een virtueel computernetwerk: de verschillende programma's stellen de hosts voor en D-Bus bezorgt de infrastructuur voor de communicatie. Op de desktop zijn het vooral KDE, GNOME en de Hardware Abstraction Layer (HAL) die gebruik maken van D-Bus.

Voorheen was het nogal versnipperd op dit gebied. KDE 2 en 3 gebruikten DCOP (Desktop Communication Protocol). GNOME had voorheen een andere manier voor onderlinge processcommunicatie: Bonobo.

De Qt-toolkit heeft D-Bus-functionaliteit sinds versie 4. KDE 4 heeft DCOP vervangen ook door D-Bus en GNOME heeft Bonobo in stappen uitgefaseerd. In theorie is er dus communicatie mogelijk tussen de twee platforms.

Bij Qt 4 komt er een programmaatje mee waarmee je kan communiceren met alle programma's die op D-Bus zijn aangesloten: qdbus. Degenen die voor het KDE 4-tijdperk met het dcop-commando werkten zullen hier redelijk snel mee uit de voeten kunnen.

Aan de slag met qdbus

Laten we met iets eenvoudigs beginnen: het opvragen van de gegevens van het nummer dat in Amarok 2.0 wordt afgespeeld.

Wanneer je qdbus uitvoert krijg je een hele reeks namen te zien. Dit zijn alle processen die momenteel aangesloten zitten aan D-Bus. KDE-applicaties zijn te herkennen aan processen die met org.kde beginnen en GNOME-applicaties met org.gnome. Amarok is een KDE-applicatie, en als Amarok bezig is met een track af te spelen staat org.kde.amarok ertussen. We voeren nu het volgende commando uit:

$ qdbus org.kde.amarok
/
/AudioOutputs
/AudioOutputs/0
/KBookmarkManager
/KBookmarkManager/amarok
/KBookmarkManager/kfilePlaces
/KDebug
/KIO
/KIO/Scheduler
/MainApplication
/Player
/TrackList
/amarok
/amarok/MainWindow
/amarok/MainWindow/actions
/amarok/MainWindow/actions/options_configure_keybinding
/amarok/MainWindow/actions/options_configure
/amarok/MainWindow/actions/file_quit
/internal
/internal/PhononXine

Amarok bestaat uit verschillende (KDE-)componenten die ieder een D-Bus-interface aanleveren. Laten we één zo'n interface eens nader bekijken door de naam van de interface achter het vorige commando te schrijven:

$ qdbus org.kde.amarok /Player
signal void org.freedesktop.MediaPlayer.CapsChange(int)
method int org.freedesktop.MediaPlayer.GetCaps()
method QVariantMap org.freedesktop.MediaPlayer.GetMetadata()
method void org.freedesktop.MediaPlayer.Next()
method void org.freedesktop.MediaPlayer.Pause()
method void org.freedesktop.MediaPlayer.Play()
method int org.freedesktop.MediaPlayer.PositionGet()
method void org.freedesktop.MediaPlayer.PositionSet(int)
method void org.freedesktop.MediaPlayer.Prev()
method void org.freedesktop.MediaPlayer.Repeat(bool)
method void org.freedesktop.MediaPlayer.Stop()
method int org.freedesktop.MediaPlayer.VolumeGet()
method void org.freedesktop.MediaPlayer.VolumeSet(int)
method QDBusVariant org.freedesktop.DBus.Properties.Get(QString interface_name, QString property_name)
method QVariantMap org.freedesktop.DBus.Properties.GetAll(QString interface_name)
method void org.freedesktop.DBus.Properties.Set(QString interface_name, QString property_name, QDBusVariant value)
method QString org.freedesktop.DBus.Introspectable.Introspect()

Zoals je ziet bestaat een interface uit verschillende functies. Regels die met method beginnen zijn beschikbaar om aangeroepen te worden vanaf de commandoprompt. We willen dus de trackinformatie opvragen van de track die momenteel in Amarok speelt. De functie GetMetadata geeft deze informatie. Ook nu gebruiken we het vorige commando als basis en zetten er de functienaam (zonder haakjes) achter:

$ qdbus org.kde.amarok /Player org.freedesktop.MediaPlayer.GetMetadata
album: No Line On The Horizon
artist: U2
arturl:
audio-bitrate: 198
audio-samplerate: 44100
comment:
genre: Rock
location: file:///home/bram/Muziek/U2-No_Line_On_The_Horizon/02-magnificent.mp3
mtime: 320000
rating: 0
time: 320
title: Magnificent
tracknumber: 2
year: 2009

We hebben onze trackinformatie te pakken nu. Er zijn ook functies waarmee je iets in het programma kan veranderen. Vaak moet je daarbij ook enkele parameters meegeven. Neem bijvoorbeeld de volgende functie:

$ qdbus org.kde.amarok /TrackList org.freedesktop.MediaPlayer.SetLoop true

SetLoop neemt één argument met een booleaanse waarde. Na dit commando zal Amarok de huidige afspeellijst blijven herhalen.

Enkele handige commando's

Het moet toegegeven worden, echt transparant is dit alles niet. Je moet maar net weten waar je bepaalde functionaliteit moet zoeken (als het programma dat überhaupt wel in de D-Bus-interface heeft opgenomen). Daarom komt hier een lijstje van commando's die je een beetje op weg kunnen helpen. Al deze commando's zijn uitgevoerd met KDE 4.2.2, maar ze zouden geldig moeten blijven in de KDE4-series.

  • Zet alle verbonden accounts op Afwezig in Kopete:
    qdbus org.kde.kopete /Kopete org.kde.Kopete.setOnlineStatus Away
  • Zet alle verbonden accounts weer terug op Online in Kopete:
    qdbus org.kde.kopete /Kopete org.kde.Kopete.setOnlineStatus Online
  • Stelt een statusbericht in in Kopete:
    qdbus org.kde.kopete /Kopete org.kde.Kopete.setStatusMessage "Dit statusbericht is mede mogelijk gemaakt door D-Bus"
  • Laat KMail je email controleren:
    qdbus org.kde.kmail /KMail org.kde.kmail.kmail.checkMail
  • Sla alle documenten op in Kate. Merk op dat dit een dialoogje op kan roepen als een document nog geen bestandsnaam heeft, dus dan is de muis alsnog nodig. Let ook op de procesnaam in het commando: hier staat de PID van Kate in. Zorg dus dat je die weet voordat je het commando aanroept.
    qdbus org.kde.kate-11494 /kate/__KateMainWindow_1/actions/file_save_all trigger
  • Een KDE-programma (netjes) afsluiten:
  • qdbus org.kde.naam /MainApplication quit
  • Schakel je computer met bevestiging die 30 seconden de tijd geeft om te annuleren (voorzichtig!):
    qdbus org.kde.ksmserver /KSMServer org.kde.KSMServerInterface.logout 1 2 2

Toepassingen

Je zou je af kunnen vragen wat voor nut het heeft om zo'n lang commando te typen als een druk op de knop (of zelfs een sneltoets) volstaat. Toch zijn er enkele scenarios waarbij dit goed te gebruiken is.

  • SSH

    Het kan zijn dat je op een machine inlogt over SSH en dat daarop een KDE-sessie draait. Je kan op deze manier zonder dat je toegang hebt tot de X-server toch nog het noodzakelijke doen (zoals je werk opslaan of programma's afsluiten zoals hierboven is beschreven). Persoonlijk heb ik dit terug in de KDE3-tijd eens misbruikt op de PC van m'n vader. Ik moest hem online spreken maar hij was vergeten de instant messenger aan te zetten. Ik startte Kopete op onder zijn gebruiker en met een DCOP-commando zorgde ik dat zijn account online kwam.

    Let er op dat dit vanaf een andere console niet meteen werkt, qdbus heeft de $DISPLAY-variabele nodig. Deze moet ingesteld zijn op het scherm waarop de X-server momenteel draait. Vaak volstaat het volgende commando:

    export DISPLAY=:0
  • Scripts

    D-Bus komt ook van pas vanuit scripts. Het voorbeeld hieronder combineert enkele commando's die hierboven zijn gegeven. Het haalt de trackinformatie op van Amarok 2 en maakt er vervolgens een statusbericht van in Kopete. Zo zien mensen wat je momenteel aan het luisteren bent:

    #!/bin/sh

    export DISPLAY=:0
    MESSAGE=""
    NOWPLAYING=`qdbus org.kde.amarok /Player org.freedesktop.MediaPlayer.GetMetadata`
    if [ $? = 0 ] && [ -n "$NOWPLAYING" ]; then
    ARTIST=`echo "$NOWPLAYING" | sed -ne 's/^artist: \(.*\)$/\1/p'`
    TRACK=`echo "$NOWPLAYING" | sed -ne 's/^title: \(.*\)$/\1/p'`
    MESSAGE="Listening to $ARTIST - $TRACK"
    fi

    qdbus org.kde.kopete /Kopete org.kde.Kopete.setStatusMessage "$MESSAGE"

    Het eerste wat we doen is de trackinformatie ophalen. Met [ $? = 0 ] wordt gekeken of qdbus succesvol werd uitgevoerd. In het geval dat Amarok niet draait zal dit statuscode 1 teruggeven. Vervolgens wordt uit de uitvoer de juiste informatie gefilterd en in een tekst geplaatst. Deze tekst wordt vervolgens weer met D-Bus naar Kopete gestuurd.

    Om je status automatisch bij te werken, kan je dit scriptje uitbreiden met een while-loop, of in cron plaatsen die dit iedere minuut uitvoert.

  • Onderlinge communicatie van KDE-componenten

    Amarok biedt een uitgebreide interface aan voor het afspelen van tracks. Dit wordt gebruikt om bijvoorbeeld een 'afstandsbediening' te maken buiten Amarok om. Zo kan je bijvoorbeeld in je taakbalk een afspeel- en stopknop plaatsen die via D-Bus de muziek kan besturen.
    Een andere toepassing is bijvoorbeeld opgedoken rondom Bluetooth-telefoons. Wanneer het Bluetooth-programma detecteerde dat een telefoon buiten bereik van de computer was, zette het Kopete automatisch in afwezigheidsmodus. Dit is een mooie illustratie van wat er allemaal mogelijk is.

Conclusie

Tot zover een introductie tot het gebruik van D-Bus en in het bijzonder qdbus. Dit artikel focuste met name op KDE-programma's, maar in feite is dit concept natuurlijk ook over te dragen naar GNOME of andere programma's die aangesloten zijn op D-Bus.

Update 11 april 2009:

Iets wat ik me later realiseerde was dat Qt ook nog een grafische D-Bus-browser aanbiedt: qdbusviewer. Het biedt niet meer functionaliteit dan het commando qdbus, maar het maakt het verkennen van de mogelijkheden wel een stuk comfortabeler.