let us not mourn telepathy-python

But let us instead celebrate gobject-introspection.

While there has been no official announcement, I think it’s probably time we declared telepathy-python to have passed away. Deprecated. In the great attic of the sky.

The python-telepathy client-side bindings have been in a state of disrepair for a long time now, not able to do the heavy lifting that other bindings such as tp-glib and tp-qt4 have been focusing on.

telepathy-butterfly is not really maintained, isn’t supported properly by empathy master, and is looking to be replaced in the future by the MSN Live XMPP support. In the meantime bug #663829 migrates existing butterfly accounts to telepathy-haze. I’m not sure about telepathy-sunshine, but I suspect it also won’t work with the latest Empathy.

Through work I started, and a bunch of other people have continued, telepathy-glib client-side bindings have been growing increasingly more introspectable as time passes. This is now used by gnome-shell, and it works pretty well.

Since someone asked today, here’s how you set your global presence in Python:

from gi.repository import TelepathyGLib as Tp
from gi.repository import GObject

loop = GObject.MainLoop()
am = Tp.AccountManager.dup()
am.prepare_async(None, lambda *args: loop.quit(), None)
loop.run()

am.set_all_requested_presences(Tp.ConnectionPresenceType.AVAILABLE,
    'available', 'Set by script')

Unfortunately we can’t introspect the service-side bindings, they do some things that are very creative and clever, but that gobject-introspection just doesn’t understand. Which means you can’t write a CM using PyGObject yet. The solution, I think, is likely to come with a future, GVariant-based telepathy-glib, but I’m still trying to figure out how we can make things (like mixins) work in a way that g-i can understand.

heading to IM, Contacts and Social hackfest

I am currently sat in Dubai airport on my way to the IM, Contacts and Social hackfest in at Collabora’s office in (real) Cambridge. Hopefully this week will get some cool progress made it integrating Telepathy and Folks into GNOME 3.

My attendance is sponsored by my employer, Collabora.

~

In recognition of the occasion, I actually started running GNOME 3. I’m enjoying it, except for missing Cantarell1 and this focus follows mouse bug. I am looking forward to the reappearance of the world clocks.

Also it seems you can no longer make the screen lock on suspend, which feels like a big deal, because I’m the kind of person to leave a sleeping laptop lying around. If no one already has a good solution to this, I might write a fix using a gnome-shell extension.

~

It used to be that you could set different timeouts for screen blanking vs. screen locking. I’ve lived without this feature in recent years by remembering to press the lock-screen button on my keyboard, but I had this strange idea on the plane that screen locking can also be tied-in with IM presence.

At the moment the screen blanks after the idle time, which is equivalent to the away status in Telepathy (the computer is idle, save some power, also if the user has sound turned off, she won’t see your text). Whereas I wanted the screen to lock automatically after an extended period of being away, the xa status in Telepathy?

For the moment (it may change this week) Empathy is responsible for setting the presence in Mission Control, setting away in response to gnome-session and setting xa itself. Either the session could add a concept of extended away, which I could wire up to lock the screen. Or I could listen to the presence change from Mission Control. This could always be another shell extension.

  1. maybe I’m just missing a package, I’m running the gnome3-team ppa on Ubuntu natty []

The Architecture of Open Source Applications

Some time ago, I was asked if I would write a chapter on Telepathy for a new book on software architecture: The Architecture of Open Source Applications.

Finally today, the book as been released. You can read it online (or jump straight to my chapter) or purchase a hardcopy1. The work is available under the Creative Commons Attribution 3.0 Unported license, and I believe translation is especially welcome.

I’ve not read the whole thing yet. Some of it I last read in draft. I have to find a quiet evening, but what I’ve read so far has been quite interesting. Authors talk about the mistakes, solutions and workarounds they ran into when putting their software together. It’s nice to know you’re not the only one who occasionally hacks together something you’re just not that proud of.

Thanks should go to the editors, Amy Brown and Greg Wilson, as well as the other authors, reviewers and contributors for making this book real.

  1. If you do purchase a hardcopy, buy it from Lulu. All the proceeds from the sale of this book go to Amnesty International, and they are given more money if you buy it from Lulu than from a vendor like Amazon. []

Telepathy GIT repositories move to freedesktop.org

Although Telepathy has always been a freedesktop project, for the longest time the repositories were hosted on Collabora’s git server (I blame the original use of darcs). Sjoerd informed me today that this is no longer the case and the repositories have finally been moved to freedesktop.org where they belong.

The repositories are still available read-only on git.collabora.co.uk for the time being. It’s not known to me when they might be moved to an archive directory or go away completely.

You can update your remotes with git remote set-url, in shell it looks like this (assuming your origin is Telepathy upstream):

# set NEW_URL appropriately
NEW_URL=git://anongit.freedesktop.org/telepathy/
# NEW_URL=ssh://git.freedesktop.org/git/telepathy/

for d in telepathy-*; do
  ( cd $d && \
    git remote set-url origin $NEW_URL$d && \
    git remote update -p origin )
done

~

Also in case you missed it, telepathy-sofiasip, the SIP connection manager has been renamed to telepathy-rakia. SofiaSIP is the name of the library that telepathy-rakia uses and since Telepathy connection managers are often referred to by the last part of their name (e.g. gabble, haze, butterfly), calling it sofiasip was ambiguous. Like all Telepathy names, there is a tenuous link between the name of the protocol and the name of the CM.

LD_PRELOAD GObject lifetime debugging tool

For years and years I’ve dreamt of a tool that would show me what GObjects are currently alive, and let me have a look at information about them. Today, while trying to debug a particularly horrid reference leak (program wedged under refdbg, and without being able to script SIGTRAP I’ve never found this method useful), I actually started writing the tool.

The tool uses LD_PRELOAD to replace g_object_new() — it should really replace g_object_newv() and g_object_new_valist() also, but I didn’t need those — to install a weak reference on the created objects to track their lifetime.

The result of which is something like this:

[danni@adelie src]$ LD_PRELOAD=libgobject-list.so \
    GOBJECT_LIST_FILTER=Gabble GABBLE_PERSIST=1 \
    /usr/lib/telepathy/telepathy-gabble 
 ++ Created object 0x9912530, GabbleGatewayPlugin
 ++ Created object 0x990c460, GabblePluginLoader
 ++ Created object 0x9917ab8, GabbleJabberProtocol
 ++ Created object 0x99172f0, GabbleConnectionManager
...

You can then list the currently living objects and their reference counts by sending SIGUSR1.

[danni@adelie src]$ killall -USR1 telepathy-gabble
Living Objects:
 - 0x9b47038, GabblePresence: 1 refs
 - 0x990c460, GabblePluginLoader: 2 refs
 - 0x9918ae0, GabbleRosterChannel: 1 refs
 - 0x991cb38, GabbleIMChannel: 1 refs
...

This by itself was useful in showing which object wasn’t finalized but should have been (and why my object in question also hadn’t finalized), but didn’t show me who was still holding the reference.

My hunch was that the problem was a reference cycle between two objects, so I hacked a bit of code into my tool to list the “connection” property on all objects that had it. [In Telepathy Connection Managers, objects are typically meant to let this go when connections become disconnected.]

  while (g_hash_table_iter_next (&iter, (gpointer) &obj, NULL))
    {
      GObjectClass *klass;
      GObject *conn;

      g_print (" - %p, %s: %u refs\n",
          obj, G_OBJECT_TYPE_NAME (obj), obj->ref_count);

      klass = G_OBJECT_GET_CLASS (obj);
      if (g_object_class_find_property (klass, "connection") != NULL)
        {
          g_object_get (obj,
              "connection", &conn,
              NULL);
          g_print ("\t + connection = %p\n", conn);
          if (conn != NULL)
            g_object_unref (conn);
        }
    }

This showed me which object was still holding a ref it should have let go. [Now I just need to work out why, the code in question is in an abstract base class, for which 5 of 6 concrete classes work correctly.]

If you’re interested, the code is in Git.

The tool could still benefit from a lot of work. For instance, the filtering is pretty basic at the moment and it should support all the ways to create GObjects. Originally I had envisioned this tool as a GUI window that popped up, so that you could click on an object and view all of its properties, connected signals, etc. That would be pretty neat actually.

Update: cassidy has already contributed by adding a listing of the objects remaining when a program exits and thus found a leak in Empathy. Awesome!

taking over

dbus-send --session --print-reply --dest=org.freedesktop.DBus / org.freedesktop.DBus.ListNames | grep string | grep -v '":' | wc -l
57
dbus-send --session --print-reply --dest=org.freedesktop.DBus / org.freedesktop.DBus.ListNames | grep string | grep 'Telepathy\|Empathy' | wc -l
13

With Empathy using GtkApplication, somewhere around 23% of the well-known names on my D-Bus session bus belong to Telepathy or Empathy.

It’s slowly taking over.

higher level channel requesting in telepathy-glib

Thanks to the awesome work of Guillaume, telepathy-glib 0.11.12 now includes high-level API for requesting communications channels via Mission Control (the Channel Dispatcher). API is provided both for channels you wish to handle, or channels you want someone else to handle. The API uses the same asynchronous patterns as used in GIO.

For instance, to request a text channel to a contact that you want someone else (i.e. Empathy) to handle:

GHashTable *props = tp_asv_new (
    TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING, TP_IFACE_CHANNEL_TYPE_TEXT,
    TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT, TP_HANDLE_TYPE_CONTACT,
    TP_PROP_CHANNEL_TARGET_ID, G_TYPE_STRING, "escher@tuxedo.cat",
    NULL);
 
TpAccountChannelRequest *request = tp_account_channel_request_new (TP_ACCOUNT (account),
    props, G_MAXINT64 /* current time */);
 
tp_account_channel_request_ensure_channel_async (request,
    NULL, NULL, _channel_ready, NULL);
 
g_hash_table_destroy (props);
g_object_unref (request);
static void
_channel_ready (GObject *request,
    GAsyncResult *res,
    gpointer user_data)
{
  GError *error = NULL;
 
  if (!tp_account_channel_request_ensure_channel_finish (
      TP_ACCOUNT_CHANNEL_REQUEST (request), res, &error))
    handle_error (error);
 
  ...
}

I’ve spent some time this week updating telepathy-glib examples to take advantage of new APIs, and they’ve all become noticeably shorter. The last two missing pieces of the puzzle are high-level wrappers for channel types (we have prototypes for tubes: stream, dbus) and a library of GTK+ widgets (a libfolks-gtk maybe?).

the Telepathy book has moved

By popular demand, I’ve moved the Telepathy Developer’s Manual http://telepathy.freedesktop.org/doc/book/ rather than having it in my personal webspace.

Yes, it’s still a work in progress. No, it still doesn’t cover VoIP (I’ve been waiting for the new Channel.Type.Call to undraft). Yes, most of the examples still require porting to Mission Control 5 (this week maybe?). No, it doesn’t cover Qt4 yet (patches accepted).

introspecting tp-glib and converting DBus-GLib GValues to GVariants

Telepathy is a modular framework. At the very heart of Telepathy there is a specification that describes how the various connection managers, clients and other components interact with each other. The specification is written in terms of a set of D-Bus APIs.

Telepathy takes full advantage of what’s provided by D-Bus, which is why you see so many different interfaces in the specification (one day I’ll write more about this), but one thing it makes frequent use of is variant types and specifically string->variant maps (known in D-Bus parlance as a{sv} maps).

a{sv} maps are used by the DBus.Properties.GetAll() method, to return all of the properties in an interface (which are all of different types), but in Telepathy they’re used more generically with namespaced properties to make requests for communication channels and collate information. The types are specified by the key names.

Telepathy-GLib exposes these maps as GHashTables of element type string->GValue, which actually works quite well in C. Telepathy-GLib registers specific GTypes with GLib via DBus-GLib and we have generic utility functions to unpack the GValues into native C types. For simple types, this also works really well in the bindings. For simple types (int, string, boolean, etc.) GJS converts the GValue values in our map into native JS values and things are pretty neat. Unfortunately this does not work for complex, container types (e.g. sa{sv}as); GLib doesn’t provide enough API to query the complete type information of the GValue’s contents, thus it’s not possible to introspect.

The GLib solution to this problem is GVariant, a way to store values that keeps all of the type information in an easily accessible way. If tp-glib exposed a{sv} maps as string->GVariant, we would easily be able to unpack the complete type in GJS or PyGI. GDBus uses GVariant for passing around types, but porting tp-glib to GDBus would take a lot of effort and radically break the API and ABI, so just isn’t feasible at this stage.

But there is a solution! Unsurprisingly, DBus-GLib has the information to recursively unpack a GValue registered with itself, it requires this in order to marshal those GValues into a D-Bus message, but it also exposes this API so we can use it for our own ends. Thus it becomes possible to convert these GValues to GVariants! In fact here is some sample code (Telepathy-GLib is not strictly required, it’s only being used here to provide test cases). I’m hoping this utility can be provided as part of DBus-GLib and then used to provide alternative API for tp-glib that can be exposed to the bindings.

To complete the circle, I wrote GVariant unpacking for GJS, but it needs reworking to only unpack when explicitly requested instead of implicitly always.

Update: bug #28715 provides a proposed patch to dbus-glib.