All the Old Showstoppers

okay, new rule1: it’s okay to install a GObject property like this:

pspec = g_param_spec_string ("title",
			     "Title",
			     "The title of the item",
			     NULL,
			     G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_TITLE, pspec);

instead of the usual way you see in other GObject-based libraries, where we l33t h4x0rs dispense from the use of an explicit GParamSpec variable. this is especially true if you are trapped in 1983 and are still using an ANSI 80×25 terminal — though you should probably know that here, in 2008, 100+ columns are safe.

oh, and fill out the name and blurb fields of the property: GObject provides a little bit of introspection, but if you willfully ignore it then we can just forget about stuff like the GObject-Introspection project.

please, every time you install a property using a line like this:

g_object_class_install_property (
	gobject_class, PROP_TITLE,
	g_param_spec_string ("title", NULL, NULL, NULL,
	                     G_PARAM_READABLE | G_PARAM_WRITABLE));

an unfortunate incident will involve a bucket of puppies and a belt sander.

comments saying “gobject sucks you should be using ${ZEALOTS_OWN}” will be deleted without mercy because they miss the point by a hundred and fortyseven miles

  1. apologies to Bill Maher []

Road to Somewhere

well, after eating my dog food for a while, it seems that Tweet is starting to get more useful.

first of all, now Tweet has an authentication dialog which allows you to enter your username and password the first time you run it:

Authentication/1

and even verify them beforehand:

Authentication/2
Authentication/3

then you get the list of statuses from the people you’re following:

Loading

you can scroll around using your mouse, and tap a row to get more informations about the status and the user:

Navigation

click on the screenshot…

as you can see, the UI is geared towards the touchscreen usage, but I plan to add key navigation soon.

still, there’s a lot to add: support for viewing your own statuses, direct messages, the list of people you’re following and the people following you — even the error messages are just printed to the console, even though I’m working on that.

the bits I’m most proud of:

  • the GTK+ integration: I’m retrieving the style information straight from the GtkWindow embedding the Clutter stage, and even if I had to fight with the utter mess that is the themeing code, I was able to gather enough to make Clutter play nice with a GTK+ environment1;
  • the small animation API I implemented on top of the Clutter animation framework, requiring a single function (plus two completely generic classes) to tween an actor between two states; for instance:
    tweet_actor_animate (info, TWEET_LINEAR, 250,
                         "y", tweet_interval_new (G_TYPE_INT, y + padding, 100 + padding),
                         "height", tweet_interval_new (G_TYPE_INT, 10, (height - (100 * 2))),
                         "opacity", tweet_interval_new (G_TYPE_UCHAR, 0, 196),
                         NULL);
    

    this is the code that animates the status information actor that appears overlayed on top of the status view2; I’d like to thank pippin for the idea about the API behaviour;

  • Twitter-GLib, the generic API for accessing Twitter throught its RESTful API, which thanks to LibSoup has been a breeze to write even in a clunky and not-at-all-web-two-point-oh-buzzword-compliant language like C;
  • the fact that Tweet is written in a very reusable manner (apart from the base scrollable list which comes from Tidy), with every piece neatly abstracted into its own class.
  • finally, the fact that after almost a year of basically working on libraries only I can still sit down and get an application from scratch to a usable state in a couple of weeks in my spare time — even if I have to write a library to get it done. :-)

by the way: is any artist out there interested in making an icon for Tweet? I really would like to avoid using Twitter’s own icon.

  1. in the screencast the scrollbar handle color, for instance, comes from the theme as well as the font []
  2. this kind of utility API is easy to achieve given the power and flexibility of the underlying framework — but it obviously limits what you can and cannot do, and if you ty to coerce it into being more generic you start losing bits and pieces and a simple API starts getting in your way instead of helping you; that’s why Clutter‘s animation framework might seem complicated at first: it’s trying very hard to allow you to build whatever animation you have in mind instead of limiting you []

Good Intentions/2

gtk+: I’ve been working again on the RecentManager and in trunk you’ll see some new stuff, namely:

  • use GIO to determine the MIME type of a URI, on every platform supported
  • use the file monitoring API to avoid polling the storage file
  • add a GtkSettings property for clamping the recently used resources list to a 30 days limit

more stuff I’d like to add is:

  • small parser changes to GBookmarkFile, to reflect changes in the spec
  • bulk addition, for applications storing multiple items when quitting
  • new API needed to follow the usability review in bug 349541
  • moving the RecentItem icon code to GIO, and add API to extract the thumbnail

twitter: I’ve been using Twitter a lot in the past two weeks; it’s nice, it makes it easier to copy and paste a quote or a thought, and the 160 characters limit is an interesting challenge. As it’s been ages since I last wrote an application1, I decided to start writing a Twitter reader/writer — using GTK+, Clutter and Tidy; without much thinking, I opened gvim and started writing code in C2 — so, the obvious thing that happened was that I ended up writing a library yet again in order to use Twitter’s web API. luckily for me, libsoup has now a really nice API to work with; all you need is GET and POST to their RESTful API, retrieve the result, parse it through JSON-GLib, hide everything inside a new GObject and you have a wrapper around a web service. the application, you say? oh, I was sure I forgot something. well, it’s coming along — it just needs some work still.

  1. lately all I’ve been doing was writing libraries []
  2. hey, that’s what I do for a living, it’s hard to switch off; plus, I could reuse some of the platform libraries []

Berlin/5

last post of the Berlin Hackfest series, written on the last minutes of day 5

today was “wrap up” day. we got together in the room used for the presentations and summed up all our work during the various sessions of the week. it turned out that the amount of work, even though not reflected by the wiki page, was really enormous; the introspection guys worked a lot and now that they have received a lot of input, they are going to rework things and kick ass even more. apparently, Behdad decided that I would tackle the GL integration inside GDK — which, of course, I’d really like to do; the GL integration, and a GDK wrapper for the GLX_texture_from_pixmap (and the equivalent call for the other platforms) would obviously be the primary way to integrate Cairo 2D high quality drawing and GL 3D and hardware acceleration in a simple way. and this is a step forward the implementation of a scene graph inside GTK+.

in the meantime, I’m — as Ryan would put it — deeply recursing. it all started on tuesday, when I decided to start hacking on a real application with Vala using all the bits and pieces a modern GTK+ application requires: GtkUIManager, about dialogs, command-line switches. the application was supposedly going to read the new GTest framework reports, and allow comparing of multiple runs in a fast way. this, in turn, led to some bugs filed against Vala GTK+ bindings. working around these issues, I also found out that the libxml-2.0 bindings in Vala — which I need to parse the GTest report XML — require a lot of pointers usage and are, in general, quite sub-obtimal, due to the very C oriented API. while investigating on a substitute, I found out XmlReader — the cursor-based XML traversal API that .Net and other high-level languages implement1. Thus, today at a coffe shop2 I started hacking very quickly on a rough implementation of a XmlReader GObject class which, as of at this moment works quite nicely:

  XmlReader *reader = xml_reader_new ();
  GError *error = NULL;

  if (xml_reader_load_from_file (reader, "book.xml", &error))
    g_error ("Unable to parse book.xml: %s", error->message);

  xml_reader_read_start_element (reader, "book-info");

  xml_reader_read_start_element (reader, "author");
  author = g_strdup (xml_reader_get_element_value (reader));
  xml_reader_read_end_element (reader);

  xml_reader_read_start_element (reader, "title");
  title = g_strdup (xml_reader_get_element_value (reader));
  xml_reader_read_end_element (reader);

  xml_reader_read_end_element (reader);

  g_print ("The author of %s is %s\\n", title, author);

  g_free (title);
  g_free (author);
  g_object_unref (reader);

and you’re done. at this moment, I’m cleaning it up and adding the gtk-doc API reference to the build3. I’m probably going to add the generic read() method, so that:

  while (xml_reader_read (reader))
    {
    ...
    }

will work as expected. it’s, as usual, code replication — but I’m going to need it anyway, so it’s good code replication.

  1. Even libxml-2.0 implements it, even though it suffers from the same issues of its DOM API, and it’s still not GObject-based []
  2. Behdad is right: a coffee shop without any Internet connectivity makes wonders with your productivity levels []
  3. When I write new libraries, I usually stub out the API and document it at the same time; now I started to add the GTest units before I even implement the API []

Stinging Velvet

Clutter – If release 0.4 rocked hard, release 0.6 of Clutter will blow your mind away. Just to list some features landed in the past couple of weeks after ClutterScript got in:

  • new event handling, borrowing from the W3C DOM event – that is, two event phases: capture, which traverses the scene from the stage to the actor that received the event, and bubble which traverses the scene from the actor to the stage. You can block the event chain in any point of both phases by simply returning TRUE in the signal handlers (like GTK+); kudos to mallum and Pippin
  • improved text scaling, at least for downscaling at ~50%; kudos to Pippin
  • build and test on win32 using the SDL backend, complete with VS2005 build files; kudos to tf
  • time-based timelines, so you can define a ClutterTimeline by giving its length in milliseconds; and without even breaking the API.

Still, there’s plenty more coming – so keep looking at trunk.

JSON-GLib – The code base has been consolidated a lot while working on ClutterScript, so I feel confident about making a release of the out-of-tree repository. The release is bagged, tagged and signed as json-glib-0.2.1 in the git repository1. You can grab the tarball here. Work on seamless GObject-JSON (de)serialization will continue in the master branch towards a 0.4.0 release. Update@2007-10-16T23:30+0100: obviously, as soon as I got back home and checked the repository I found two bugs in the generator code; hence, brown paper bag release 0.2.1. Tarball, documentation and tag updated.

  1. As usual, at http://folks.o-hand.com/~ebassi/git/json-glib.git []

Porcelain

Today I committed to Clutter trunk ClutterScript, the initial support for defining the scenegraph using external files. You can think of it as the GtkBuilder equivalent for Clutter.

During the 0.3 development cycle we considered using XML and JSON, and opted for the latter because while XML is quite easy for applications to write, JSON is more geared towards human to read1. Also, JSON syntax is really parser-friendly, with only three barewords and six symbols.

Another nice thing about JSON is that many high-level languages already have some JSON module, so manipulating data streams would be quite easy for, let’s say, Perl or Python before feeding those streams to Clutter.

Defining a simple scene with JSON and ClutterScript is quite easy:

{
  "id" : "main-stage",
  "type" : "ClutterStage",
  "fullscreen" : true,
  "children" : [
    {
      "id" : "red-button",
      "type" : "ClutterRectangle",
      "x" : 100,
      "y" : 100,
      "width" : 100,
      "height" : 100
      "color" : "#ff0000ff"
    },
    {
      "id" : "green-button",
      "type" : "ClutterRectangle",
      "x" : 300,
      "y" : 100,
      "width" : 100,
      "height" : 100
      "color" : "#00ff00ff"
    },
    {
      "id" : "blue-button",
      "type" : "ClutterRectangle",
      "x" : 600,
      "y" : 100,
      "width" : 100,
      "height" : 100
      "color" : "#0000ffff"
    }
  ]
}

This will draw a red, a green and a blue square, 100×100 pixels of size, inside a full screen stage.
You can then retrieve the "main-stage" object (as well as any other object using its id) and connect signals and manipulate them with the usual Clutter API.

At the moment ClutterScript is not 100% complete – I still need to add support for defining behaviours (mostly a matter of defining an object syntax); complex properties parsing; merging (and, possibly, unmerging) of “snippets” of objects. Plus, obviously, more sanity checks in the scene building code.

To parse JSON there are a few C libraries, but I opted for writing a GObject-based one – which, in one of my usual moments of lack of originality, I called JSON-GLib. Clutter uses an in-tree copy because I might need API changes to make Clutter parsing code easier, but the library is already auto-tooled, tested and 100% documented (it is missing GObject deserialization, but that will have to wait). JSON-GLib is released under the terms of the LGPL and it’s available in my personal git repository, which you can clone with the usual:

  git clone http://folks.o-hand.com/~ebassi/git/json-glib.git

Update@2007-10-09T15:07+0100: Just landed in trunk: defining behaviours (not every type, complex types like the path-based ones are still to be implemented), merging tests and more sanity checks. Defining a rotate behaviour boils down to:

{
  "id"          : "rotate-behaviour",
  "type"        : "ClutterBehaviourRotate",
  "angle-begin" : 0.0,
  "angle-end"   : 360.0,
  "axis"        : "z-axis",
  "direction"   : "cw",
  "alpha"       : {
    "timeline" : { "loop" : true, "num-frames" : 300, "fps" : 60 },
    "function" : "sine"
  }
}

Really soon now: all behaviours, complex properties and more.

  1. obviously nothing prevents adding an XML parser, and use both []

Flying Teapot

Clutter 0.4.0 was, finally, released two days ago. Not only the core and add-on libraries but also the language bindings are available for this new stable release cycle.

We already started working on trunk for the 0.5/0.6 development cycle, which should hopefully lead up to another stable release in six months; there already is a nice list of features we are working on, but I’d like to see more requests, more patches ( ;-) ) and people working on even more language bindings.

Take it or leave it

After the comments on my latest blog post, I got back at Unique and did some rearrangements in the code base. Now the backends are all compiled in (obviously, depending on whether you have the dependencies to compile them) and the backend to be used can be defined at runtime. The default backend is chosen at compile time and can be overridden by setting the UNIQUE_BACKEND environment variable. Obviously, if you launch an instance with UNIQUE_BACKEND=dbus and another one with UNIQUE_BACKEND=bacon you will have two instances running – but that’s only to be expected.

I’ve also updated the API to something I can probably call “semi-frozen” (small API additions notwithstanding); the constructor changed to always accept a startup notification id (it will try to be clever and find it for you if you pass NULL, though) and allows you to define custom commands with a single call.

As usual, you can clone the Git repository from here:

  git clone http://www.gnome.org/~ebassi/git/unique.git

or grab the tarball for 0.9.20.9.3 from here.

I’ll keep working on making a 1.0.0 release at GUADEC (probably it’ll happen right at GUADEC), API/ABI stable and with the Xlibs backend. Then I’ll resume working on the GtkApplication class, which will have the Unique features but will (hopefully) be integrated in GTK+.

Update@2007-07-12T12:54+0100: New release, with full API reference documentation, a couple of stupid bugs squashed and workspace support.

Strange news from another star

I’ve been promising a release of GtkUnique for a while now, but work and other stuff got in the way of the namespace change-slash-rewrite. Yesterday I finally got around finishing the porting of the Unix domain sockets backend (or “bacon”) so I cooked up a preliminary release with the D-Bus and Bacon backends working. You can find the tarball here or, if you’re feeling in hacking mood, you can check out the git repository from here:

  git clone http://www.gnome.org/~ebassi/git/unique.git

the unique-0.9.1 is the tag for this release. I’ll work on finishing the port of the Xlibs backend and target a stable 1.0.0 release for GUADEC.

The API of Unique changed a bit since the last GtkUnique release, and I think it’ll change a bit more in order to be usable with the smallest impact possible. Now you can register custom commands and there’s convenience API for sending strings and URI lists; the command registration and construction API might change to something similar to the GtkDialog API – and I might switch to a more signal based approach (construct the message payload inside a signal handler) before 1.0. I also might add a –replace command line switch that gets slurped and does The Right Thing for you.

The biggest change is happening under the hood, though; with this release, the UniqueApp instance will request the specified name as soon as it is created, so you’ll be guaranteed to either be the first running instance or be able to send messages to the currently running instance at the same moment that the UniqueApp constructor returns. Hence, no more race conditions between the constructor and the “is running” request. Finally, the “window watching” functions have been removed – even though I might add a “watch window” function to handle the startup notification sequence for you (now that we have the API to do that in GTK+ 2.11).

This release also means that the code in SVN under the gtkunique module is to be considered deprecated. I’m going to ask the svnmaster to move it into the attic, as the delta is too big for a simple check-in. As soon as 1.0.0 is out I’ll also ask the release-team for “blessing” Unique as a dependency, so if you want your module to depend on it you’ll be able to safely do it. Again, sorry for taking this long to finish up this work.

Update@2007-07-09T15:16+0100: I’ve just rolled a 0.9.1 to fix some build issues and add licensing terms. Thanks to Christian Persch for the heads up.

Time is Running Out

Today I committed a couple of fixes to GtkRecentManager and I thought it was worth mentioning them on pgo.

Up until now, GtkRecentManager instances were available either via the gtk_recent_manager_new() constructor – which left the memory management duties to the developer – or via the gtk_recent_manager_get_default() which tried to do the right thing, by returning a singleton instance to be shared inside an application. The master plan was having the singleton attached to the GdkScreen to take advantage of the lifetime management of the screen done by GTK+ and cleanly dispose the recent manager when the screen was closed. This approach would have worked well, except for two tiny details:

  1. if you change screen, gtk_recent_manager_get_default() will return a different instance
  2. GdkScreen are never closed unless you do that explicitly.

So much for the master plan.

Thanks to Morten Welinder, who did some very appreciated detective work on it, it was decided to switch to a more common approach, with a static variable and a private synchronisation function that gets called when the main loop level reaches zero. What does this mean, for the application developer? First of all, two deprecations: both gtk_recent_manager_get_for_screen() and gtk_recent_manager_set_screen() are deprecated as of GTK+ 2.12 and should never be used again (the first evaluates to gtk_recent_manager_get_default() and the second to a NOP, if you ever decide to compile with GTK_DISABLE_DEPRECATED turned off); second of all, no more juggling around with the screen changes: multiple calls of gtk_recent_manager_get_default() will always return the same instance of the GtkRecentManager object – which you should never unref. Obviously, if you were creating your own recent manager instance with the gtk_recent_manager_new() constructor, none of this matters and you’ll have to handle the manager lifetime by yourself.

Another change I committed was the switch to the g_timeout_add_seconds() for the polling of the recent files storage file. Since the timeout was set to every N seconds I decided that the lifespan of my laptop’s battery was more important than having a millisecond precision on a stat() call. In other news, laptop owners around the world rejoice as one. Since every signal under GTK+ is emitted under the assumption that the emitter is inside the GDK master lock, the newly added gdk_threads_add_*() functions weren’t fit for my cunning plan of using the approximate timeout source; for this reason, I added a g_timeout_add_seconds_full() inside GLib and the equivalent code directly inside GtkRecentManager.