Steve Frécinaux

Mathusalem API presentation

Tuesday was released the fourth development release of Mathusalem. It does not feature gtk-doc integration yet, so probably it’s worth having a short overview of the API. This will focus on the C API, but it’s very very similar to the D-Bus one, since there is a 1-to-1 match between D-Bus interfaces and GInterfaces.

Warning: This API is not set in stone. It will change. Much. I promise.

On the task owner

So your program has something to do, say copying five files from one place to another. Let’s create a task so that it can be displayed by Mathusalem.

MalemFactory *factory;
MalemTask *task;
static const gchar *interfaces[] = {
        "org.gnome.Mathusalem.FileTransfer",
        NULL
};

factory = malem_factory_client_get_default ();
task = malem_factory_register_task (interfaces);

This creates a task that implements the FileTransfer interface. It means that you’ll be able to work with the common task methods (which belong to org.gnome.Mathusalem.Task), but also the file-transfer-related methods.

You have to know that for Mathusalem, each task is a composition of several interfaces, and the only one that each task must implement is the Task one. Since it is required, there is no need to put it in the interface list.

In the same manner, the task object you receive implements the GInterfaces corresponding to the interfaces you requested. So you can use their methods, but trying to use another GInterface method will raise an error.

The factory object is Mathusalem itself. It is somewhat the task manager, and is unique. This is why you get it from malem_factory_client_get_default(). From the task owner, the only relevant method is the register_task one. It creates a task on the server.

Then, your transfer is cancellable. So what you do is register the “abort” action, so clicking on the “stop” button from Mathusalem will actually stop the task.

malem_task_add_action (task, "abort", NULL, NULL);

g_signal_connect (task, "action-triggered",
                  G_CALLBACK (task_action_triggered_cb),
                  NULL);

the NULL values just mean that we don’t care about the values: we will use the default ones. If it was a custom action you should define a label and a picture using those. But “abort” as well as “pause” and “start”, are known from the server and he already has labels and pictures for those.

When the user clicks on a button in the Mathusalem UI, a “action-triggered” signal is sent. So connecting to it will just allow us to react to those clicks. The signal handler prototype is:

static void
task_action_triggered_cb (MalemTask    *task,
                          const gchar  *action_name,
                          gpointer      user_data)

You can continue the task initialization by setting data for additional interfaces, and once you’re done, start the task by calling malem_task_start (task). Then you just have to play with the methods to update the task status:

  • malem_task_pause (task)
  • malem_task_abort (task)
  • malem_task_set_progress (task, (guint) progress)

Once it is finished, you dispose your object like any other one, by unreferencing it.

On the client

On startup, what the client probably wants is to get a list of interesting tasks.

MalemFactory *factory;
MalemTask **tasks;

factory = malem_factory_client_get_default ();
tasks = malem_factory_list_tasks_for_interface (factory,
                                                "org.gnome.Mathusalem.FileTransfer");

This will just return the tasks that implements the interface we are interested in. If you have other needs, you can just get the whole task list by using malem_factory_list_tasks (factory).

Since we want to be aware of new interesting tasks, we do so:

g_signal_connect (G_OBJECT (factory), "task-registered",
                  G_CALLBACK (on_task_registered), NULL);

The callback prototype is:

static void
on_task_registered (MalemFactory        *factory,
                    MalemTask           *task,
                    const char         **interfaces,
                    gpointer            user_data)

Then, for each interesting task, we can connect on interesting signals: “status-changed”, and “progress-changed”. Don’t forget to ref the task object too!

You can trigger an action on the task (just as the user could do by clicking on a button) by calling malem_task_trigger_action (task, "abort").

Here was the most useful bits of the API. There are several other methods available, I enjoin you to go and look in the headers (for the C API) and in the XML files (for the D-Bus API) in the tarball.