telepathy-glib GObject-Introspection and TpBaseClient

In Telepathy libraries such as telepathy-glib, telepathy-python and telepathy-qt4 there are two kinds of API. There's what we call low-level API, which is a direct wrapping of the D-Bus API exposed by Telepathy components and automatically generated from the Telepathy specification; and high-level API, which is hand-written and calls the low-level API internally with the goal of making it easier to implement things with Telepathy.

It's relatively easy to expose the low-level API into your language by writing an output module on top of our specparser and using your language's native D-Bus support. However writing a high-level API is a pain in the neck, and requires you to redo a lot of work that's already been done once.

Basically this sucks, so over the last couple of weeks a few of us have been working to support GObject-Introspection for the telepathy-glib high-level API. This means that we can now expose telepathy-glib functionality into languages such as Javascript (via GJS) and Python (via PyGI). We're choosing not to bind the low-level API that telepathy-glib exports, mostly because it's not very pretty and languages have better ways to expose this (N.B. this does create possible ordering problems because you are likely to have two separate DBusConnections). We're also working on extending telepathy-glib to make more things easier.

One such extension is TpBaseClient and its subclass TpSimpleObserver, which are designed to make it significantly easier to write a Telepathy clients such as Observers (TpSimpleHandler is coming soon).

The introspected bindings are not yet production ready, we're still going through and checking everything is annotated correctly, and we've also exposed a few limitations in GJS and PyGI (e.g. GArray support) that don't yet have fixes merged.

Still, putting this all together, it's now possible to write the basis of a Telepathy Observer in Javascript:

const Tp = imports.gi.TelepathyGLib;
const Mainloop = imports.mainloop;

function observe_channels(observer, account, connection, channels,
                          dispatch_op, requests, context, user_data)
{
    print("observe_channels");

    print("account = " + account.get_object_path());
    print("connection = " + connection.get_object_path());

    for (let i in channels) {
        let channel = channels[i];

        print("channel = " + channel.get_object_path());
    }

    if (dispatch_op != null)
      print("dispatch_op = " + dispatch_op.get_object_path());
    else
      print("dispatch_op = (null)");

    for (let i in requests) {
      let request = requests[i];

      print("request = " + request.get_object_path());
    }

    context.accept();
}

let dbus = Tp.DBusDaemon.dup();
let observer = Tp.SimpleObserver.new(dbus, true, "JSObserver", true,
                                     observe_channels);

observer.add_observer_filter({
  "org.freedesktop.Telepathy.Channel.ChannelType": Tp.IFACE_CHANNEL_TYPE_TEXT,
});

try {
    observer.register();
    Mainloop.run("");
} catch (e) {
    print("ERROR: " + e);
}

All of this work is now merged into telepathy-glib master, and will be released as part of the telepathy-glib 0.12.

Creative Commons Attribution-ShareAlike 2.5 Australia
This work by Danielle Madeley is licensed under a Creative Commons Attribution-ShareAlike 2.5 Australia.