Worked out an approach for versioning GTK+ in future, to improve the balance between stability and speed of development. This has turned into a wiki page.

I demoed Dunfell and added support for visualising GTasks to it. I don’t know how much time I will have for it in the near future, so help and feedback are welcome.

There was a detailed discussion of portals for Flatpak, including lots of use cases, and the basics of a security design were decided which allows the most code reuse while also separating functionality. Simon has written more about this.

I missed some of the architectural discussion about the future of GTK+ (including moving some classes around, merging some things and stripping out some outdated things), but I believe Benjamin had useful discussions with people about it.

Collabora is sponsoring snacks throughout, and is sending 5 of us along for the hackfest. Thank you also to the other companies who are sending or letting people come — I know of Red Hat, Endless Mobile, Codethink and Canonical (please let me know if I’ve forgotten anyone!).

The interface is designed around polling, potentially-blocking I/O. What’s ‘potentially-blocking’ about it? The timeout parameter. Set it to zero for non-blocking behaviour, where the functions will return G_IO_ERROR_WOULD_BLOCK if they would block. Set it negative for blocking behaviour, where the functions will not return until they can do at least some I/O. Set it positive for timeout behaviour, where the functions will block for the given number of microseconds, then return G_IO_ERROR_TIMED_OUT if they managed to perform no I/O.

Currently, the API (particularly GInputMessage and GOutputMessage, due to the way they are used as in-out parameters) doesn’t support introspection. This can be added in future if needed by creating some convenience API for allocating and freeing the message structures as boxed types.

The grand, overarching plan is for this to appear in a libnice version near you, some time soon, exposing the whole of an ICE connection as a GDatagramBased.

Announcing dbus-deviation, a small tool and set of libraries for automatically checking whether a D-Bus interface has broken API between two releases of a piece of software, developed as part of my work at Collabora.

Why?

If you have a large software project, worked on by multiple developers, it might not be clear when D-Bus interfaces change. For example, they might be pulled in from another repository, or might be accidentally changed without anyone noticing.

Breaks in the D-Bus API of a project (when it’s supposed to be stable) are potentially worse than breaks in its C API, because they can only be detected at runtime — when client applications suddenly error out half-way through an operation because they’ve called a D-Bus method with the wrong argument type. At least with C API breaks, the compiler will catch the break.

(In this respect, I guess D-Bus APIs are actually a form of ABI — a runtime interface, rather than a compile-time interface.)

How?

dbus-deviation provides a utility called dbus-interface-diff, plus some GNU Make glue to plug it into your build system. It only works with git: for each tagged release of your project, it uses git-notes to store copies of all the D-Bus interfaces you care about, in their state at the time of that release. They’re stored as introspection XML; if you have that XML committed into the repository anyway, the git-note becomes a ref to the existing file blob, and takes up virtually no space at all. The dbus-interface-diff tool then does a diff between two XML files (for example, one stored for the most recent release, and the one currently in your working tree), and flags up any forwards- or backwards-incompatibilities.

What?

A backwards-incompatibility, as far as dbus-deviation is concerned, is one where existing clients will not work against new versions of the D-Bus service, for example because a method they use has been removed.

A forwards-incompatibility is one where new versions of clients may not work against old versions of the D-Bus service, for example because they use a method which has been added in a new version of the API.

Traditionally, projects care about preventing backwards-incompatible API changes, and don’t care so much about forwards-incompatibilities. dbus-deviation lets you set your desired stability policy.

All feedback is very much welcome. One area I feel is still a little awkward is how dbus-deviation integrates with make dist — it forces use of a pre-push git hook to update the remote git-notes for the API signatures of newly pushed release tags. That needs to be set up by each developer who releases a project (using make dist) — any suggestions for improving this are welcome.

Before I start, an addendum to my last post about the DX hackfest: I wish to thank Codethink for sponsoring dinner one night of the event. I forgot to include that in my original post, sorry! Thanks again to all the companies who let employees attend: Endless, Codethink, Canonical and Red Hat.

Now, to some of the results of the hackfest. In the last week or so, I’ve been working on expanding the GNOME programming guidelines, upstreaming various bits of documentation which Collabora have been writing for a customer who is using the GNOME stack in a large project. The guidelines were originally written in the early days of GNOME by Federico, Miguel and Morten; Federico updated them in 2013, and now they’ve been expanded again.

As part of the series of tea time talks we do within Collabora, I recently got to refresh my knowledge of STUN, TURN and ICE (the protocols for NAT traversal) and give an introductory talk on how they all fit together within the context of libnice.

Since the talk might be useful (and perhaps even interesting) to a wider audience, I’ve made it available: slides, handout and source (git). It’s under CC-BY-SA 4.0. Please leave comments if anything is unclear, incorrect, or could do with more in-depth coverage!

For the past several months, Olivier Crête and I have been working on a project using libnice at Collabora, which is now coming to a close. Through the project we’ve managed to add a number of large, new features to libnice, and implement hundreds (no exaggeration) of cleanups and bug fixes. All of this work was done upstream, and is available in libnice 0.1.8, released recently! GLib has also gained a number of networking fixes, API additions and documentation improvements.

Firstly, what is libnice? It’s a GLib implementation of ICE, the standard protocol for NAT traversal. Briefly, NAT traversal is needed when two hosts want to communicate peer-to-peer in a network where there is at least one NAT translator between them, meaning that at least one of the hosts cannot directly address the other until a mapping is created in the NAT translator. This is a very common situation (due to the shortage of IPv4 addresses, and the consequence that most home routers act as NAT translators) and affects virtually all peer-to-peer communications. It’s well covered in the literature, and the rest of this post will assume a basic understanding of NAT and ICE, a topic about which I recently gave a talk.

Conceptually, libnice exists just to create a reliable (TCP-like) or unreliable (UDP-like) socket which connects your host with a remote one in a manner that traverses any intervening NATs. At its core, it is effectively an implementation of send(), recv(), and some ancillary functions to negotiate the ICE stream at startup time.

Highly related, the original receive API has been augmented with scatter–gather support in the form of a recvmmsg()-like API: nice_agent_recv_messages(). Along with appropriate improvements to libnice’s underlying socket implementations (the most obscure of which are still to be plumbed in), this allows performance improvements by batching messages, reducing the number of system calls needed for communication. Furthermore (perhaps more importantly) it reduces memory copies when assembling and parsing packets, by allowing the packets to be split across multiple non-contiguous buffers. This is a well-studied and long-known performance technique in networking, and it’s nice that libnice now supports it.

So, if you have an ICE connection (stream 1 on agent, with 2 components) exchanging packets with 20B headers and variable-length payloads, instead of:

libnice has also gained non-blockingvariants of its I/O functions. Previously, one had to explicitly attach a libnice stream to a GMainContext to start receiving packets. Packets would be delivered individually via a callback function (set with nice_agent_attach_recv()), which was inefficient and made for awkward control flow. Now, the non-blocking I/O functions can be used with a custom GSource from g_pollable_input_stream_create_source() to allow for more flexible reception of packets using the more standard GLib pattern of attaching a GSource to the GMainContext and in its callback, calling g_pollable_input_stream_read_nonblocking() until all pending packets have been read. libnice’s internal timers (used for retransmit timeouts, etc.) are automatically added to the GMainContext passed into nice_agent_new() at construction time, which you must run all the time as before.

Finally, FIN/ACK support has been added to libnice’s pseudo-TCP implementation. The code was originally based on Google’s libjingle pseudo-TCP, establishing a reliable connection over UDP by encapsulating TCP-like packets within UDP. This implemented the basics of TCP, but left things like the closing FIN/ACK handshake to higher-level protocols. Fine for Google, but not for our use case, so we added support for that. Furthermore, we needed to layer TLS over a pseudo-TCP connection using GTlsConnection, which required implementing half-duplex close support and fixing a few nasty leaks in GTlsConnection.

This past week, I’ve been working on a Clang plugin for GLib and GNOME, with the aim of improving static analysis of GLib-based C projects by integrating GIR metadata and assumptions about common GLib and GObject coding practices. The idea is that if running Clang for static analysis on a project, the plugin will suppress common GLib-based false positives and emit warnings for common problems which Clang wouldn’t previously have known about. Using it should be as simple as enabling scan-build, with the appropriate plugin, in your JHBuild configuration file.

I’m really excited about this project, which I’m working on as R&D at Collabora. It’s still early days, and the project has a huge scope, but so far I have a Clang plugin with two major features. It can:

Load GIR metadata1 and use it to add nonnull attributes based on the presence (or absence) of (allow-none) annotations.

Add warn_unused_result attributes to functions which have a (transfer container) or (transfer full) return type.

Add malloc attributes to functions which are marked as (constructor).

Constify the return types of (transfer none) functions which return a pointer type.

By modifying Clang’s abstract syntax tree (AST) for a file while it’s being scanned, the plugin can take advantage of the existing static analysis for NULL propagation to function calls with nonnull attributes, plus its analysis for variable constness, use of deprecated functions, etc.

So far, all the code is in two ‘annotaters’, which modify the AST but don’t emit any new warnings of their own. The next step is to implement some ‘checkers’, which examine (but don’t modify) the AST and emit warnings for common problems. Some of the problems checked for will be similar to those handled above (e.g. warning about a missing deprecated attribute if a function has a Deprecated: gtk-doc tag), but others can be completely new, such as checking that if a function has a GError parameter then it also has a g_return_if_fail(error == NULL || *error == NULL) precondition (or something along those lines).

I’ve got several big ideas for features to add once this initial work is complete, but the next thing to work on is making the plugin effortless to use (or, realistically, nobody will use it). Currently, the plugin is injected by a wrapper script around Clang, e.g.:

This injects the -load $PREFIX/lib64/clang/3.5/libclang-gnome.so -add-plugin gnome arguments which load and enable the plugin. By specifying GIR namespaces and versions in GNOME_CLANG_GIRS, those GIRs will be loaded and their metadata used by the plugin.

Please note that it’s alpha-quality code at the moment, and may introduce program bugs if used during compilation, so should only be used with Clang’s -analyze option. Furthermore, it still produces some false positives, so please be cautious about submitting bug reports to upstream projects ‘fixing’ problems detected by static analysis.

Actually, it loads the metadata from GIR typelib files, rather than using the source code annotations themselves, so there is a degree of data loss incurred due to the limitations of the typelib binary format. ↩

It works using the Bluetooth Phone Book Access Profile (PBAP), which allows a computer to download a phone’s address book as an array of vCards. libfolks will automatically do this for any phone which is paired with the computer (and which isn’t blocked), establishing a connection with any (paired, non-blocked) phone in range.

We’ve only been able to test this with a limited number of phones, so further real-world testing and feedback would be greatly appreciated. To do so, grab the latest version of libfolks from git (https://git.gnome.org/browse/folks/log/), build it and run folks-inspect (making sure that the ‘bluez’ backend is not disabled in ~/.local/share/folks/backends.ini, if you’ve created and customised that file).

As is the design of libfolks, this is not intended as a solution for synchronising contacts between your phone and your computer, but it does provide a handy way of accessing contacts on your phone from GNOME Shell or Contacts, or from other consumers of libfolks data.

Note that the backend only supports BlueZ 5 and explicitly doesn’t support BlueZ 4.

How does GNOME generate thumbnails for files? It uses a collection of programs called thumbnailers, each one generating thumbnails for a specific set of content-types of files. For example, totem-video-thumbnailer generates thumbnails for video files using GStreamer; evince-thumbnailer generates thumbnails for PDFs and other document files.

To generate a thumbnail, an appropriate thumbnailer program is selected then executed, passing it the path of the file to thumbnail, plus a path to write the thumbnail image to. If thumbnailing succeeds, the thumbnailer should have written the image to disk before terminating; but if thumbnailing fails, no image should be written, and the thumbnailer should return a non-zero exit status.

Thumbnailers are chosen by examining a series of .thumbnailer files in $PREFIX/share/thumbnailers. Each is in a simple key-file format:

TryExec: Optional. The name of the the thumbnailer program in the current $PATH. This allows the calling code to quickly check whether the thumbnailer exists before trying to execute it.

Exec: Required. The command to execute the thumbnailer. It supports a few different parameters which are replaced before calling the thumbnailer: %u is the URI of the file being thumbnailed; %i is its filename; %o is the filename of the image file to be written to; %s is the maximum desired size of the thumbnail image (in pixels); and %% is a literal percent character.

So in the evince-thumbnailer file above, the command passes the requested thumbnail size, then the input file’s URI, then the path for the output image file to evince-thumbnailer.

The code to examine and call a thumbnailer is in gnome-common’s GnomeDesktopThumbnailFactory class, which handles looking up the right thumbnailer script, building and executing the command for it, and loading the resulting thumbnail image into a GdkPixbuf.

Thumbnail caching is supported by GnomeDesktopThumbnailFactory. When calling a thumbnailer, the path passed for the output image file is in ~/.cache/thumbnails/$SIZE/. The cached image file is given a (probably) unique filename, generated by hashing the original file’s URI, so the thumbnail can be looked up in future. gnome-desktop supports two sizes of thumbnails: ‘normal’ and ‘large’. Normal thumbnails are up to 128×128 pixels, whereas large thumbnails are up to 256×256 pixels. Thumbnails which are larger than this are scaled down before being cached, and non-square thumbnails are scaled so their largest dimension is at most 128 or 256 pixels.

gnome-desktop also handles failed thumbnails. If a thumbnailer can’t generate a thumbnail for a file (e.g. because the file is corrupt or because the right video codecs aren’t available), it returns a non-zero exit status. gnome-desktop then writes an entry to ~/.cache/thumbnails/fail/gnome-thumbnail-factory/ which is named after the hash of the input file URI (just like a successful cached thumbnail). For future queries for thumbnails for that file, GnomeDesktopThumbnailFactory can immediately return an error after looking up the fail entry.

If a file changes content, GnomeDesktopThumbnailFactory knows to generate a new thumbnail because each cached image has associated metadata (stored as PNG tEXt keys) storing the full URI of the thumbnailed file (to check for hash collisions) and its last modification time at the point of thumbnailing. If the stored modification time doesn’t match the file’s current one, a new thumbnail is generated.

“I don’t care. Show me the code.”

As an example of this, I present gnome-directory-thumbnailer, which generates thumbnails for directories (which is possible with a few small fixes to gnome-desktop). I wrote this as part of a project for my new employer, Collabora. It generates a thumbnail for a directory by heuristically choosing its ‘most interesting’ file (or subdirectory) and taking the thumbnail from that. It works fairly well for generic directories, but there’s great scope for improving the heuristics to cater for directories which match different templates (e.g. a directory of audio files for an album; a directory containing an automake project; a mounted DVD directory; etc.).

If you want to write your own thumbnailer, a good place to start is with the gnome-thumbnailer-skeleton by Bastien Nocera. It provides the generic wrapper code for command line parsing and output handling which would otherwise get rewritten for each new thumbnailer.