Disappointing linux.conf.au keynote

The linux.conf.au anti-harassment policy states:

Harassment includes:

  • sexual images in public spaces

Yet Friday morning’s keynote, Mark Pesce, progressively violated this policy, starting with comic sexual images and culminating with a soft-core, lesbian bondage photograph.

Sorry, a “PG-13” rating does not excuse this behaviour. Yes they were wearing lingerie, it’s still pornographic. And for those who are going to continue to insist it wasn’t: the porny presso bingo card (via Skud).

Update: the chief linux.conf.au organiser made an apology for this morning’s keynote during the closing ceremony.

Virgin Mobile internet sporadicness

Perhaps someone can help me out here.

In January I switched from Optus to Virgin Mobile on my mobile phone. Optus 3G on my phone tended to work quite reliably, but on Virgin it tends to get backed up or just drop my packets from time to time. Tracerouting (via mtr) seems to suggest it’s a problem with Optus’ IP network1, where it will begin to drop packets between two routers on that network.

Googling comes up with other people complaining about this on Whirlpool, but nothing that looks like a solution. Has anyone else run into this? If so, how did you resolve it?

[1] Even though Virgin Mobile is carried on Optus’ phone network, I was surprised to see IP addresses from Optus’ IP network.

making my C more like Python

Asynchronous programming in C can be such a pain. You’re always creating little structs in order to pass around user_data. So often I find myself wishing it were like Python, and I could just create an anonymous tuple.

Then I had this crazy idea.

DBus is always passing around tuples. dbus-glib represents these as GValueArrays. They’re so ubiquitous that telepathy-glib added utility functions to deal with them: tp_value_array_build() and tp_value_array_unpack().

We can use them like this:

my_request_async (obj, my_callback,
  tp_value_array_build (2,
    G_TYPE_POINTER, my_pointer,
    G_TYPE_UINT, my_uint,
    G_TYPE_INVALID));

With the callback:

static void
my_callback (GObject *obj,
    GAsyncResult *result,
    gpointer user_data)
{
  gpointer my_pointer;
  guint my_uint;
 
  tp_value_array_unpack (user_data, 2,
      &my_pointer,
      &my_uint);
 
  ...
 
finally:
  g_value_array_free (user_data);
}

In my specific use case, I was making requests for a property, and then needed the generic callback to know which property the request was for. I could have copied and pasted the request multiple times, or get increasingly meta:

#define MY_REQUEST_ASYNC(prop) \
  my_request_async (obj, prop, \
      my_callback, tp_value_array_build (2, \
        G_TYPE_POINTER, my_pointer, \
        G_TYPE_UINT, prop, \
        G_TYPE_INVALID));
 
  MY_REQUEST_ASYNC (PROP_1);
  MY_REQUEST_ASYNC (PROP_2);
 
#undef MY_REQUEST_ASYNC

Where this gets really useful is when you’re having to copy or reference your members: strings, objects, hash tables, etc.. You no longer need to write new() and free() functions for each structure. GValue already knows how to take care of it.

my_request_async (obj, my_callback,
  tp_value_array_build (3,
    G_TYPE_OBJECT, my_obj,
    G_TYPE_STRING, "escher",
    G_TYPE_BOOLEAN, TRUE,
    G_TYPE_INVALID));

Everything will be released when you call g_value_array_free().

You could go further. For optional numbers of arguments you could use an a{sv} map (telepathy-glib also has utility methods to manipulate these, i.e. tp_asv_new()).

Unfortunately not everyone has telepathy-glib in their stack. I bet you could also achieve the same result using GVariant with g_variant_new(), g_variant_get() and g_variant_unref(). Store your pointers as type ‘t’ and remember to cast them to (guint64) for correct var-args alignment. Unfortunately GVariant can’t do your ref-counting.

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).

Collabora @ GUADEC 2010

You might have seen the t-shirts around, there are quite a few (twenty!) Collaborans at GUADEC this year.

IMG_8997m

Like a game of bingo, see if you can spot them all: Gustavo Noronha, Travis Reitter, Youness Alaoui, Felix Kaser, Guillaume Desmottes, Nicolas Dufresne, Jonathon Jongsma, Olivier Le Thanh Duong, Eitan Isaacson, Marco Barisione, Tomeu Vizoso, Cosimo Cecchi, Olivier Crête, Danielle Madeley, Sjoerd Simons, Rodrigo Novo, Senko Rašić, Thomas Thurman, Philip Withnall and Louis-Francis Ratté-Boulianne.

There are also all twelve members of Collabora Multimedia here.

Collabora is hosting a beach party on Thursday, starting from 7pm. Word on the street says there will also be ninja t-shirts available at some point.

g_variant_equal() and dictionaries

For anyone using g_variant_equal() with a type containing a dictionary, you should the aware that, somewhat unexpectedly in my opinion, g_variant_equal() only returns true if (and only if) the keys in the dictionary are in the same order (GVariant implements dictionaries as an array of key-value pairs).

You can resolve this by using a function that recursively checks for semantic equivalence (such as this one).

I’m sure I’m not going to be the only person to find this useful. I’ve filed this as bug #622590.

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.

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