Ikke's Blog

Category: Linux

May 16
More messaging

Been busy lately due to uni work, so not much hacking time. I did enhance that messaging thing a little (not working on other stuff I'd like to work on yet as they're potential SoC projects :-)).

wall, write and other pty based communication support still isn't in there as I didn't manage to get something working (yet). Must be doing something completely wrong somehow.

I did add a "Reply" option to the incoming messages though. Currently the reply dialog is not HIG at all, no I18N support, it's crap PyGTK code, but it does work somewhat.

Here's a little demo (1MB animated GIF screencast, thanks Byzanz (and Company)!)

I made a first "release" for people who's want to play with this. You can find the tarball here, but note it needs work: checking for Python stuff in configure.in, fixing Python code, adding I18N support, get the dialog code inside the C daemon, as using a helper is plain stupid (I use a helper as it's pretty easy to create a GUI using PyGTK quickly).

TODO: incoming message throttling (so one can't flood you using smbclient in a shell for loop), I18N (damn intltool 's been driving me crazy), nicer UI, other messaging "protocol" support, get a Telepathy backend out of this (jdub's idea),...

May 9
Good old messaging

Davyd talked about integrating good old messaging systems like talk, wall, write and even WinPopup into the GNOME desktop. As it looked like a fun thing to do, I got my hands down on it today.

I still couldn't figure out how to catch wall and other pty-based messages, but I'm sure I will be able to get them working too.

At the moment, WinPopup messages work:

Maybe in-time one should be able to click the message popup and get a simple window allowing the user to reply on the incoming message, but thats to be done later on, first I want to get wall and talk requests working fine.

A little change to smb.conf is needed for this (the "message command" line should be set, I'm using a Python script to send the messages), and one file in the D-BUS system.d to allow the user Samba uses to spawn the message command ("nobody" on my system) to send messages on the system bus.
Obviously pty-based messages shouldn't need a callout anywhere.

Current code isn't ready for release yet (at all), I'll try to get what I got into good shape asap.

Apr 19
New prototype

Lots of traffic on GIMPNet today, many different and interesting things were discussed between some GNOME hackers. But I guess others will write about those things (Philip? Jeff?).
Anyway, more related to myself and my own project (yeah, CDIS, you know): I had a great talk with Robert "Robot101" McQueen, who gave some very sensible insights in the D-BUS system, and how I could (ab)use it.
First of all, last night I was thinking about the D-BUS glossary a little, and came to the conclusion that "interfaces" might at a certain level be compared to "namespaces" instead of "interfaces", at least in some point of views. Might be interesting if you try to "get" D-BUS. Questions? Leave a comment ;-)

After this talk and some help from J5, #1 python-dbus guru, I managed to get a new sample setup working. In this new design, there is no central daemon at all any longer, which is great, obviously. Some changes/enhancements to the D-BUS bindings might be necessary though (I hate the fact you can't get the sender service/object path in a signal handler!).

As a picture says more than a thousand words, first open up this screenshot. Code's here.
As you can see, first the user starts his favorite media player, RhythmBox, and spins his favorite song (1). In the background, a screensaver application is running (in the sample I started it after RB, but hey, its a sample) (2). After a while (3 seconds ;-)), the user starts his VoIP softphone, Ekiga (3). As the user is very popular, he almost immediately receives a call, and accepts it (4).
As you can see, Ekiga knows about music players, and asks them to pause playback. RB is CDIS-aware, and stops playing (5). Obviously, the music player should do a generic "Paused" signal here (see later). Next, Ekiga sends out a signal on the org.freedesktop.CDIS.SoftPhone interface, "IncomingCall". This signal can be used by any application listening for it. It is not related to pausing music players: in (4-5), Ekiga tells all music players to pause. It knows about this kind of applications, and knows how to handle them. In (6) Ekiga provides application types it doesn't know about (or, maybe more likely, doesn't want to know about, doesn't care about) to do some action based on the fact there's an incoming call.
As this is a video conference, the screensaver traps that signal, and stops his internal timer (7).
After a while, the call is over, the user disconnects (8). Ekiga sends now tells all music players they can resume playback if they were playing before (9). It also sends out a "CallTerminated" signal on the SoftPhone interface, which is again seen by the screensaver, who restarts his timer.
Then, something happens that will/should not be supported, but I just implemented it as a sample. When the screensaver decides it's time to blank the screen (11), it tells all SoftPhones to go "Idle" (12). This is not the way we should handle this in "real" applications, as a screensaver should not put SoftPhones in idle state, it should send out a signal "ScreenSaverStarted", the softphone should watch for that one, and go idle when the screen blanks. Anyway, I just wanted to give one more example of the "action" paradigm, just like "Pause" and "Resume" on the MediaPlayer interface.

As usual, the prototype code is extremely ugly, but it does show what I got in mind regarding code generation. There should be 3 "objects":

  • CdisMusicPlayer: inherited by a "real" music player, or by some internal CdisHandler object. Needs function pointers to all supported CDIS function calls. In the sample, used by RhythBox.
  • CdisMusicPlayerController: Used by code that wants to control a class of applications. Used by Ekiga to pause all music players. Only provides "active" functions that, when called, result in a change on remote objects.
  • CdisSoftPhoneClient: helper class for "generic" applications that want to be notified about things by a SoftPhone application. Used by ScreenSaver to be able to work with SoftPhone applications on the system, as the SoftPhone doesnt know about screensavers

For all of these objects, I'm sure there's some pattern for them. Philip, help! :-)

This should be fairly clear I guess... If not, ask. Lots of things can/will/should change, eg authorisation, and issue raised by sri yesterday. Don't know yet how this should be tackled thogh.
Duplicate events should be prohibited too (although this can for a big part be done by having well designed interfaces): when app A asks MusicPlayers to pause, then B does the same, and A sends a "Resume" signal, the player(s) should not resume unless B also sends the "Resume" command. This and other issues will need to be fixed!

After all a pretty fun day :-) Although you can't imagine how much I hate Blast by now :> Big thanks to all help on IRC, I should get all of you a beer at GUADEC. Sadly enough due to exams I can't be there though ;-)

Apr 18
More CDIS spam

First of all: Evolution is sooooo "1337":

Guess what: I've been thinking some more about CDIS. Yesterday I had a little discussion about it on #gnome-hackers with Robot101, who seems to have some good knowledge of D-BUS. Obviously, he rejected the idea of adding one more daemon. Indeed, it shouldn't be there, I hate it myself too, but currently it's the only solution to get things working.
He suggested to specify some well-known service and object names, and call methods on the desired services that way. This is not a possible solution though: think of someone running 2 VoIP softphones (eg Ekiga and Skype), 2 IM clients (Gossip for Jabber, aMSN for MSNP),... A service is unique for one application.

So some other solution should be found.
The best one, IMHO, is to add a method to the org.freedesktop.DBus service/object, something like "GetObjectsByInterface", which accepts a string, and returns an array of (servicename, objectpath) tupples, both strings. Using that one can do a specific call on all objects that need to be called.

Next to that, there's the versioning issue. If I remember correctly, a long long time ago this has been discussed on the D-BUS mailing list, and people decided interface versioning support wouldn't be added to D-BUS. As the CDIS interface specifications won't ever be "final", it should be possible to get around this.
It's not that hard though. We can use the standard x.y versioning system, x.y is backwards compatible with x.(y-1), so in a version bump from x.y to x.(y+1) only methods or signals can be added. Bumping x allows a complete API break.
Like this, if we release version 1.2 of the org.freedesktop.CDIS.FooInterface interface, and application FooApp got an object implementing this interface version, it should register itself to the D-BUS sessionbus, and tell it it implements org.freedesktop.CDIS.FooInterface.1.0, org.freedesktop.CDIS.FooInterface.1.1 and org.freedesktop.CDIS.FooInterface.1.2. Now if some other application wants to call a function added in version 1.1 of our spec, it just checks what service/objectpath pairs implement org.freedesktop.CDIS.1.1, and calls the method(s).
All this can be done behind the scenes by some helper library that makes it easier to make applications CDIS-aware.

As now is the time to come up with some project for Google's Summer of Code, I think it'd be great to work on this (now don't steal the idea). The only issue is: would someone be willing to mentor this?
I'd like to do the initial work somewhere under the hood of the GNOME project, if that'd be possible/allowed/accepted.

Here's a TODO:

  • Add the previously described method to the D-BUS service
  • Come up with some XML format to define CDIS interfaces, including interface version support
  • Write code generators that generate helper libraries based on these XML descriptions. Some ideas:

    • Plain C: using vtables with function pointers
    • GObject: standard GObject things like signals and GObject interfaces
    • Python: decorators
    • CLI/C#: decorators too

    The helpers should use the language-native D-BUS bindings, which makes things easier to debug (IMHO)

  • Write up an initial interface for some specific service type, and make some projects ("servers") aware of it
  • Change some other applications ("clienst") so they can make use of the servers

Regarding the helper libs: these should abstract the complete D-BUS backend and versioning issues from the actual application. An application should just initialize it, say "Hey, I'm a MusicPlayer, I want to support version x.y of the org.freedesktop.CDIS.MusicPlayer interface, here are my callbacks".
In pseudocode:

/* Hello world, I want to implement a CDIS interface */
CdisMusicPlayer *cdis_self = cdis_musicplayer_new("1.2", "com.eikke.CoolPlayer", "/com/eikke/CoolPlayer/CDISController");
/* When a client makes a "pause" call to apps implementing org.freedesktop.CDIS.MusicPlayer, please jump to myapp_playback_pause
 * This uses D-BUS methods
cdis_musicplayer_set_playback_pause_cb(cdis_self, myapp_playback_pause);
/* Hey listeners out there, I started playback
 * This sends out a D-BUS signal

Next to the server object, there are clients:

/* Hey, I'd like to control music players. I support version 1.5 of the org.freedesktop.CDIS.MusicPlayer interface */
CdisMusicPlayerClient *c = cdis_musicplayer_client_new_with_bus("1.5", my_dbus_connection);
/* If a player starts, please run this callback */
cdis_mediaplayer_client_set_playback_started_cb(c, playback_started);
/* Tell all MusicPlayers to pause */

Maybe the "object" instance isn't even necessary!

Behind the scenes, when the client calls cdis_musicplayer_client_pause(), the helper will know this method was added in version 1.1 of the specification. It will request a list of all service/object-pairs that implement the org.freedesktop.CDIS.MusicPlayer.1.1 interface from the D-BUS service, and do the Pause() call on all returned objects.
When the server "connects" to the system, telling it implements version 1.2 of the spec, the helper will connect to the session bus and will tell the D-BUS system the object implements org.freedesktop.CDIS.MusicPlayer.1.0, org.freedesktop.CDIS.MusicPlayer.1.1 and org.freedesktop.CDIS.MusicPlayer.1.2.

Like this it should be fairly trivial to make existing and new applications CDIS aware. And that's the way it should be ;-)

Obviously, an application could use "pure" D-BUS calls to handle all this itself too. But why make things so complicated?

Next to that, it should be possible to write "testkits" too, based on the XML specs. Python might be very usefull here. One test then looks up the highest version of the spec, and executes all methods new in this version on all objects claiming to implement the interface. Then it takes the last-but-one version, and does the same thing, all the way down to x.0. This way an application developer can easily check whether his application is CDIS compliant. This needs some more thinking though ;-)

Anyway, lots of things to be done, and obviously, not all of this can be done in only 2 or 3 months. Still, some results/progress can be made, and I'm 99% certain incorporating this in the desktop would be a great thing.
I know one should just apply for SoC without thinking about a mentor. I would like to know someone'd want to be mine though before applying (just to be on the safe side), so if these things interest you and you want to get some experience on the mentor side of things, please let me know!

Apr 17
Easter hacking

Writing code on easter day, after spending a day with your family (including the obligatory champagn/wine/beers) isn't such a good idea (#gnome-nl):

23:43 <@ikke> damn, help!
23:43 <@ikke> g_return_if_fail(foo() != TRUE)
23:43 <@ikke> returnt dat nu al foo() TRUE is, of FALSE?
23:43 <@ikke> ik ben helemaal aant flippen :s
23:43 <@kris> het failt als foo() != TRUE niet true is
23:43 <@kris> dus als foo() true returned
23:43 <@ikke> dus returnt als foo true is
23:43 <@kris> oh nee
23:43 <@kris> wacht ff
23:43 <@ikke> kijk, jij ook al :p
23:44 <@kris> all foo() false returnt, is foo() != TRUE true
23:44 <@kris> ja
23:44 <@kris> dus het failt als foo() true returnt
23:44 <@ikke> dus ie returnt als foo true is
23:44 <@kris> want dan is foo() != TRUE false
23:44 <+qball> leuk he :D

For the people who dont know dutch out there:

23:43 <@ikke> damn, help!
23:43 <@ikke> g_return_if_fail(foo() != TRUE)
23:43 <@ikke> does it return if foo() is TRUE, or FALSE?
23:43 <@ikke> I'm going nuts :s
23:43 <@kris> hit fails when foo() != TRUE isn't true
23:43 <@kris> so, when foo() returns true
23:43 <@ikke> so it returns when foo is true
23:43 <@kris> oh no
23:43 <@kris> wait a moment
23:43 <@ikke> look, you got the same issue :P
23:44 <@kris> when foo() returns false, foo() != TRUE is true
23:44 <@kris> yes
23:44 <@kris> so it fails when foo() returns true
23:44 <@ikke> it returns when foo is true
23:44 <@kris> caus then foo() != TRUE is false
23:44 <+qball> fun heh :D

Oh well, it's fixed :-)

I got Gentopia SVN commit access now. Gentopia is a project set up by some Gentoo devs aiming to get the Project Utopia stack properly integrated in the distribution. I committed an updated networkmanager-vpnc version, enjoy ;-)
Cleaned up the NetworkManager Gentoo backend a little too.

Could someone tell me how to mark a bug as a dupe in Bugzilla?

No CDIS mails yet, busy for some uni project (link) taking too much of my time, which I don't like actually ;-) Looks like some people picked up the idea though, great!

Next to that: jay for new fglrx drivers! Now I *will* be able to run Linux on my laptop when I get it (will not be within next 2 months though I'm afraid :-(), which is some *great* news.

<< Previous Page :: Next Page >>


Who's Online?

  • Guest Users: 465


XML Feeds

What is RSS?