Contents
Vala D-Bus Client Examples
These examples require Vala >= 0.9.2 and GLib/GIO >= 2.26
Rules for writing Vala D-Bus interfaces:
annotate the interface with [DBus (name = "...")]
convert DBusCamelCaseNames to vala_lower_case_names
add throws GLib.Error or throws GLib.DBusError, GLib.IOError to each interface method
BlueZ - Bluetooth Discovery
[DBus (name = "org.bluez.Adapter")]
interface Bluez : Object {
public signal void discovery_started ();
public signal void discovery_completed ();
public signal void remote_device_found (string address, uint klass, int rssi);
public signal void remote_name_updated (string address, string name);
public abstract void discover_devices () throws GLib.Error;
}
MainLoop loop;
void on_remote_device_found (string address, uint klass, int rssi) {
stdout.printf ("Remote device found (%s, %u, %d)\n",
address, klass, rssi);
}
void on_discovery_started () {
stdout.printf ("Discovery started\n");
}
void on_remote_name_updated (string address, string name) {
stdout.printf ("Remote name updated (%s, %s)\n", address, name);
}
void on_discovery_completed () {
stdout.printf ("Discovery completed\n");
loop.quit ();
}
int main () {
Bluez bluez;
try {
bluez = Bus.get_proxy_sync (BusType.SYSTEM, "org.bluez",
"/org/bluez/hci0");
// Connect to D-Bus signals
bluez.remote_device_found.connect (on_remote_device_found);
bluez.discovery_started.connect (on_discovery_started);
bluez.discovery_completed.connect (on_discovery_completed);
bluez.remote_name_updated.connect (on_remote_name_updated);
// Async D-Bus call
bluez.discover_devices ();
} catch (GLib.Error e) {
stderr.printf ("%s\n", e.message);
return 1;
}
loop = new MainLoop ();
loop.run ();
return 0;
}
Compile and Run
$ valac --pkg gio-2.0 dbus-bluez.vala $ ./dbus-bluez
Purple - Instant Messaging
[DBus (name = "im.pidgin.purple.PurpleInterface")]
interface Purple : Object {
public signal void received_im_msg (int account, string sender, string msg,
int conv, uint flags);
public abstract int[] purple_accounts_get_all_active () throws GLib.Error;
public abstract string purple_account_get_username (int account) throws GLib.Error;
}
int main () {
try {
Purple purple = Bus.get_proxy_sync (BusType.SESSION,
"im.pidgin.purple.PurpleService",
"/im/pidgin/purple/PurpleObject");
var accounts = purple.purple_accounts_get_all_active ();
foreach (int account in accounts) {
string username = purple.purple_account_get_username (account);
stdout.printf ("Account %s\n", username);
}
purple.received_im_msg.connect ((account, sender, msg) => {
stdout.printf (@"Message received $sender: $msg\n");
});
var loop = new MainLoop ();
loop.run ();
} catch (GLib.Error e) {
stderr.printf ("%s\n", e.message);
return 1;
}
return 0;
}
Compile and Run
$ valac --pkg gio-2.0 dbus-purple.vala $ ./dbus-purple
Skype status client (outdated example)
[DBus (name = "com.Skype.API")]
interface Skype : Object {
public abstract string invoke (string cmd) throws GLib.Error;
}
string send (Skype skype, string cmd) throws GLib.Error {
return skype.invoke (cmd);
}
void send_check (Skype skype, string cmd, string expected) throws GLib.Error {
string actual = send (skype, cmd);
if (actual != expected) {
stderr.printf ("Bad result '%s', expected '%s'\n", actual, expected);
}
}
int main (string[] args) {
try {
Skype skype = Bus.get_proxy_sync (BusType.SESSION,
"com.Skype.API", "/com/Skype");
send_check (skype, "NAME skype-status-client", "OK");
send_check (skype, "PROTOCOL 2", "PROTOCOL 2");
// if no arguments given, show current status, otherwise update
// status to first argument
if (args.length < 2) {
stdout.printf ("%s\n", send (skype, "GET USERSTATUS"));
} else {
// possible statuses: ONLINE OFFLINE SKYPEME AWAY NA DND INVISIBLE
send_check (skype, "SET USERSTATUS " + args[1], "USERSTATUS " + args[1]);
}
} catch (GLib.Error e) {
stderr.printf ("%s\n", e.message);
return 1;
}
return 0;
}
Compile and Run
$ valac --pkg gio-2.0 dbus-skype.vala $ ./dbus-skype USERSTATUS ONLINE $ ./dbus-skype AWAY $ ./dbus-skype USERSTATUS AWAY
Waiting for a service to become available (outdated example)
Waiting for a service to become available (outdated example)
Generating a vala interface from an existing DBus interface
When making an interface based on an existing DBus interface the vala-dbus-binding-tool can be used. This tool will create a interface based on an XML-file describing the DBus interface. For objects that implement the introspectable interface this file is easy to obtain. use dbus-send to get the XML printed to the screen
dbus-send --print-reply --type=method_call --dest=busname objectpath org.freedesktop.DBus.Introspectable.Introspect
alternatively d-foot can be used as a gui to browse DBus and send commands. The vala-dbus-binding-tool can be used on the obtained XML file. In it’s most basic form the command looks like this:
vala-dbus-binding-tool --api-path=”path_to_xml_file”
This will create a vala file for all interfaces provided by the object.