A quick look at Mathusalem’s young boy body
Sorry for the lack of news about Mathusalem these times, I’ve been busy on something else that had to be done quicky (crappy PHP).
But, despite quite a lot of people seem to be interested in Mathusalem, I have had no feedback at all after the first release. I know it came at a wrong time during Gnome’s release cycle, and I guess depending on a patch on latest D-Bus doesn’t help.
So what am I going to do now is explain how the interaction between Mathusalem and an hypothetical client (owner or third party) goes currently. It’s not settled in stone yet, and is not normative in anyway. Hey, it’s just for feedback from possible users, isn’t it ;-).
Thus I’m talking about both clients, first I’ll register a task, and then I’ll set up a third party client interested in that kind of tasks. The example will be a file download. So the owner of the task will be Epiphany, and the third party client, Nautilus.
Registering a task
The user clicks on a link with his right mouse button, and selects the right menu entry to actually download the linked file. He enters a file name and hits the “Save” button.
Epiphany sends a
org.gnome.Mathusalem.RegisterTask request on the daemon,
providing a set of interfaces to implement, in this case
org.gnome.Mathusalem.FileTransfer only, a title for the task (“Downloading
foobar.tar.gz”), a length (foobar.tar.gz size) and the owner name (his own).
The server returns the new task object path, for instance
/org/gnome/Mathusalem/Tasks/00000001, and fires the
Now Epiphany finishes configuring the task, by sending additional information
needed by the
FileTransfer interface, like the files involved, etc. When it
is done, it triggers the
Periodically, Epiphany can update the progress using the
and can cancel a task using provided methods. As well, the daemon can ask for
cancellation or custom actions if they have been registered by the owner, in a
way similar to what the notification daemon does.
When the progress status reaches 100% (ie when Epiphany calls the
SetProgress task method using the task length as the argument), a
Completed signal is fired and the task object disappears from the bus. The
task also supports cancellation and pause in a similar fashion.
I only covered here what’s available from the stock Task interface, but third party clients can of course use the extra functionnalities provided by the additional interface if they need to.
Being a third party client
Nautilus is interrested in epiphany’s download progression to show feedback
and avoid people trying to delete files being worked on. In a more general
fashion it cares about all tasks implementing the
since, eh, file transfers are the main Nautilus job.
So what Nautilus does on startup is getting a list of the tasks (currently,
you can only do that using introspection), then check the ones that correspond
to what you’re interested in. In our case, we check if the task implements the
FileTransfer interface, using the
ImplementsInterface task method. Then it
connects itself on the
TaskRegistered signal so that it is aware of what
tasks are registered later.
When showing a directory, Nautilus looks in the task set if there are files
in the current directory that are involved in a file transfer. If so, they are
showed in a particular fashion, for example with a small progress bar as an
emblem. When the
ProgressChanged signal is caught, the progress emblem is
updated. When the task is completed the emblem is removed, if the task is
cancelled the file is removed. That’s it.
Current implementation has a few issues that need to be addressed.
First, it does not handle tasks with unknown lenght at all. This will require some D-Bus API adaptation, I fear…
Listing running tasks is currently only possible using D-Bus introspection. I
plan to add two methods to the main object:
ListTasksWithInterface, whose behaviour seems obvious to me.
Another possible issue is the quick succession of the
Started signals (the first is emitted on registration, the second one on
actual start), on different objects (so the client has to connect to the
object to catch the second one). This could be problematic, because the
Started signal could be emitted before the client connects on it… I don’t
really know how to avoid that, especially since mergeing the two brings other
issues (for instance, the
Started signal is also emitted when a task is
unpaused). Maybe I could emit both of them when the task actually starts, so
that a registered task is always started when the third party client is made
aware of it.
Latest one is playing nice with D-Bus activation. I don’t know the subject well now, but if Nautilus connects to a signal, would it allow the daemon to be shut down when no task is registered? (especially since Nautilus is always present.)
I only exposed the use of the daemon in a general fashion. If you want to see the whole API available currently, I enjoin you to have a look at the XML files in the tarball.