Dragons and hawks

A few things which have happened recently:

Writing apps for the N900, part 4– the power of DBus

There is a contents page for all these posts.

Matters arising from last time. Several people have been replying to these posts as if I was the embodiment of the Maemo team. Although I worked on some really interesting parts of the desktop as part of a team from Collabora, I didn’t have anything to do with the package format or anything like that, and I’m writing these posts as an individual (and I welcome corrections). If you want to ask about the rationale behind anything here, there might be people who would know more at talk.maemo.org.

It’s a grand life on the buses. One of the many wonderful things to happen to the free desktop in recent years has been the invention of DBus as the glue to stick it all together; it’s gone a long way towards making Unix not suck.  Maemo sticks together with DBus just as much as GNOME or KDE do, which means we can interact with system services fairly painlessly.  And if we don’t know how to do something, we can always run dbus-monitor, use some other program to do what we wanted to do, and see how it managed.  Then we know what to google for when we’re looking for the official documentation.

Sharing is good. So today we’re going to be adding a “share” button to the app, so that we can tell our friends when we find an interesting link on reddit, and we’re going to be doing it using only a DBus client. Adding the entry to the menu is pretty trivial:

Selector with the 'share' item added

Now, let’s consider how we might want to share things with people:

  • Microblogging (twitter, identi.ca…): yes, definitely. You can very simply post a message to an account on one of these systems using DBus services provided by a library called microfeed. We’ll add an optional dependency on that library, and assume that people who are using it will already have set it up (using Mauku or something similar).
  • Email: certainly. We can interact with the email subsystem using DBus services provided by modest.
  • IM: yes, but… We could do this by putting up a dialogue from the address book, waiting for them to choose a contact, and then sending the message using Telepathy. But that’s not what we want; what we want is to start a conversation: we want to put up the IM window with the link as a sent message and allow the recipient to respond. I don’t know a good way of doing that, but maybe you do.
  • “Sharing services” usually means file hosting services like share.ovi.com, and isn’t really the sort of thing that concerns us here– even if the link’s to an image, you probably don’t want to upload a second copy of the image to your Ovi account.
  • Bluetooth: probably overkill (do people really send URLs over bluetooth? Apparently they do, actually, so maybe we’ll add that later.)

But let’s stick with microblogging and email for now. I’ve created a rather rough version of this idea as a separate file, sharing.c, in case it could be separately useful to someone else. This brings us up to raeddit-06 (diff to raeddit-05, git cloneable, and available from maemo-extras). When the user taps “Share”, this part of the program will put up another selector listing “Email” and as many microblogging services as it can find:

Sharing selector

Let’s say we choose Twitter; then the message gets posted, and we can go and check it in Mauku or the web browser:

Successful tweet

Behold the power of DBus!

Next time we’ll be adding the ability to view images in-process rather than launching the web browser, and we’ll be learning about a rather wonderful innovation called “stackable windows”.

Writing apps for the N900, part 3 — touch selectors

There is a contents page for all these posts.

Matters arising from last time: There’s been some very helpful feedback:

  • Colin Watson pointed out that debhelper 7 makes building debian/rules files far, far simpler. But Jonny Lamb told us that Maemo doesn’t ship with debhelper 7.
  • A Nokian emailed me to point out that in Maemo 5, application icons should be 48×48, and that 26×26 is from Maemo 4. (26×26 will still work, though, as we saw.)
  • Several people pointed out that the “B” in “XB-Maemo-Icon-26stands for “binary”.
  • And someone on Reddit said that “raeddit” is not a particularly wonderful name. This is true, and I’m open to better suggestions. I didn’t want to call it “reddit” without asking the reddit admins!

Today we’re going to introduce another new widget which is specific to Maemo.  The program currently opens the target site when you click a link. Last time, we promised to make it put up a menu of possibilities, instead:

Selectors. This is called a HildonTouchSelector, and it pops up (so to speak) all over the place. It can live inside any window, but it also has its own special kind of dialogue called a HildonPickerDialog.  It’s very like a combo box, but much easier to use with your fingers.

You see that the program behind the selector is blurred out: that’s to show that it’s not available. If you were to tap the blurred area, the selector would close without making any choices, and you would return to the rest of the program. You can also see that the switcher button at top left is not blurred: that’s because the selector is only modal, not system-modal. You can’t interact further with this program until you deal with the selector, but you’re free to switch to another program or start a new one.

What do we actually need? Now, before we dive into coding, let’s think about what we need from any representation of one of the lines in the menus.

  • We will need to ask it for the text to appear in the menu.
  • And it should be able to decline to appear in the menu.  For example, “vote up” should only appear if you’re logged in.
  • We will need to ask it to deploy, if it’s chosen.

How could we best implement that?

  • The fairly elegant way would be a set of singleton classes all implementing a common interface.
  • The very elegant way would be a set of DBus services.  That way, third parties could come along and add new menu options.
  • And perhaps we’ll do it the very elegant way later.  But this is a quick and simple tutorial, so…

We’ll use a set of callbacks.

  • Each callback takes a representation of the post, and a boolean– true if we’re preparing, false if we’re deploying– and returns a char*.
  • If we’re preparing, the char* is the name that will appear in the menu, and should be freed by the caller.
  • But if we’re preparing, the callback may also return NULL, to decline to appear in the menu.
  • If we’re deploying, the callback should always return NULL.
  • We promise not to ask a callback to deploy if it returned NULL in the preparation stage.

A small amount of extra work brings us to raeddit-05 (diff to raeddit-04, git cloneable, and available from maemo-extras).  This contains two callbacks: one to visit the actual site, and one to visit the comments page on reddit.  It looks like this:

Selector with two entries

It’s already much more useful this way, but it’s looking a bit bare with only two entries.  Clearly we can’t put in “vote up” or “vote down” until we allow the user to log in. We could easily put in the ability to buy a shirt, but there seem more important things to do first.

For example, every good mobile application needs a “share” button.  So next time we’ll be looking at how to add an entry which lets us IM or email the link to our friends, or post the link to twitter or identi.ca.

Writing apps for the N900, part 2 — packaging

Here’s a list of all these posts, which I’ll keep updated as I add new ones.

Matters arising from last time. A number of people asked, in the comments here and on Y Combinator, whether the change to using Qt instead of GTK in Maemo 6 will mean that Maemo 5 apps will need to be rewritten. I think it’s understandable that the switch will make people ask this question, but I don’t foresee any problems. If you want to write Qt applications, you can write them now under Maemo 5 and they’ll run; if you write GTK applications now, they will still run under Maemo 6 when it comes out. The GTK libraries won’t stop shipping with Maemo just because Qt becomes the primary toolkit.

Work behind the scenes. Today we’re talking about packaging. The version of raeddit we wrote last time downloads all the data from reddit and then puts up a window. If you’re on a slow connection, this could take several seconds. The Maemo guidelines say programs should put up a window as soon as possible, and indeed if they don’t put one up within a fairly long amount of time, the desktop assumes they’ve stalled and puts up a message to tell the user there was a problem.

So I’ve modified raeddit to put up the window immediately it launches, and to load the data in a separate thread. I was simply going to put up one of those whirly “please wait” symbols in the titlebar, but my ten-year-old user interface consultant told me that percentage-loaded bars are much more helpful. So I made the change to version 04 (diff to version 03), but since it has little to do with writing Maemo apps in particular, I’m not going to go into great detail about it. This also involved a slight change to the reddit client library, so that it could call a callback every so often to update the progress bar. The new version is backward-compatible with the old.

Where to find the files. The files we’re going to talk about are at the link; if you’d like a local copy you can get one with

git clone http://www.gnome.org/~tthurman/pics/maemo/raeddit-04/.git

So, packaging. Packaging under Maemo isn’t much different from packaging under Debian or Ubuntu. I said last time that I wasn’t going to replicate the contents of existing tutorials, and there are plenty of good packaging tutorials out there. But I’ll bend the rule a little in order to tell you what I changed to turn this into a packaged program.

The Makefile. Last time we were compiling by hand, but now we need the package to be capable of building itself. We could use autotools, but we’re trying to keep things really simple. So here’s a simple Makefile that knows how to compile and install the program.

But what do we need to install?

  • The compiled binary itself, into /usr/bin.
  • A desktop file, into /usr/share/applications. This tells the desktop where to find the program, how to launch it, and what the icon is. The moment you drop the file into that directory, through installing the package or otherwise, the desktop will pick it up and add it to the menus. The file is pretty straightforward, but if you want the full details you can read the spec.
  • The reddit alien An icon for the desktop file to refer to. We’ll use the obvious candidate– the reddit alien– and hope the reddit admins don’t mind us borrowing their logo to refer to their site.

The debian/ directory. That’s all very well, but we also need some instructions about how the package should be put together.  These live in the debian/ directory. There are only three you really need to concern yourself with:

  • debian/rules is another Makefile to explain how to package the program. (Now you understand the in-joke with that shirt). I’ve been using the same debian/rules with minor ad hoc tweaks for a while now; you can probably adapt it.
  • debian/changelog needs to say, at the very least, the date, your name, “initial release”, and that this is (say) version 0.01.
  • debian/control is mostly self-explanatory, but there’s one thing you need to know…

Adding an icon to debian/control. If we added the basic package to App Manager, it would appear like this:

Package in the Maemo repository

The blue square means that it doesn’t have an icon. App Manager isn’t going to download and unpack every package just to see whether we’ve included an icon, so we need to include one in debian/control, which will make its way into the package index. However, there’s not as much room, so it needs to be just 26×26. We’ll just show the alien’s head: All we have to do to get it into debian/control is to uuencode it (producing this result) and then put it into debian/control, indented by one space, under the heading XB-Maemo-Icon-26:. (No, I don’t know what the B is for either.)

This makes our entry in App Manager much prettier:
Package in the Maemo repository

Building it. So now all we need to do is to run dpkg-buildpackage on our package, copy it to the phone, and install it. Rather than show how to do that here, I’ll just show you a log of me doing it, since it’s quite a mechanical process.

Firing it up. And now we can load the program from the ordinary menu and run it. I would show you screenshots, but I think screencasts are far more fun. So here’s a quick video on YouTube of raeddit in use. I’ve added the current version of raeddit, such as it is, to maemo-extras, so that you can actually install it with App Manager if you feel so inclined.

One quick plug: if you’d like to see a longer screencast of a more advanced Maemo 5 program, I’m working on a location-aware system to find nearby belltowers hung for English full-circle change ringing. It uses the database from Dove’s Guide. You can see a screencast of the work in progress here.

Next time, when the user clicks a post, instead of going straight to the linked site we’ll figure out how to put up one of these menus:

Example of a Hildon selector

After that, who knows? I added a long list of possibilities to the previous post, so feel free to advocate as to which you’d like to see fixed first.

Writing apps for the N900, part 1

Ever since the N900 was announced, I’ve had people ask me whether it’s difficult, or in some cases even possible, to write apps for it.   Well, it is possible, and it’s pretty easy: let’s write a simple app together and you’ll see.  We’ll make a basic client for the social bookmarking site reddit, and I’ll call it ræddit, because I have no imagination.

First, a bit of handwaving. I’m not here to teach you C, or Glib programming, or GTK programming.  There are plenty of good tutorials about those already, and I’ll assume you know a bit about them.  In keeping with this, we won’t be writing the client’s back end; we’ll just assume that there’s a Glib-friendly client library for reddit already in existence.  Oh, look, a handy Glib-friendly client library just conveniently sprang into existence for us: source, headers.

Learn to love Scratchbox. If you’re doing any development for the N900, you’ll run into a cross-compiler toolkit called scratchbox.  It’s packaged in most major distros, so install it before you go any further.  There are two reasons you’d use scratchbox:

  • In case you don’t have an N900 handy, you can run an entire Maemo environment inside scratchbox.  But we’ll assume you have an N900 lying around, because otherwise we’d have to explain how to set up the desktop environment inside scratchbox, and that would be a bit of a diversion.  (On the other hand, this would be a good subject for a future post in this series.)
  • You can also use scratchbox just for running a compiler, in order to make binaries.  This is what we’ll do.

My First Compile. So first of all, let’s not bother with any of the graphical stuff, or with packaging.  Let’s just write a program that dumps the contents of reddit’s front page out to standard output, and then let’s run it on your phone.  Here’s a pretty minimal program to do that: raeddit-01.c.  Put that in your scratchbox, along with the reddit client library linked to above, and at the scratchbox prompt type:

apt-get install libcurl3-dev libjson-glib-dev

gcc `pkg-config --cflags --libs glib-2.0 hildon-1 json-glib-1.0 libcurl dbus-glib-1` raeddit-01.c greddit.c -o raeddit-01

There are some extra libraries listed in the pkg-config statement which we’ll be needing later.

Caveat: You may currently find a difficulty getting the correct packages installed to compile against json-glib; as of the time of writing there was a version dependency problem in the Maemo repository between libjson-glib-dev and libjson-glib-1.0-0. I solved it in a rather ugly way by downloading the package directly and doing dpkg -i --force-depends libjson-glib-dev_0.6.2-5_armel.deb. Your mileage may vary. I hope they’ve fixed this by the time you read this.  If not, you know what to do.

So anyway, you should now have a binary called raeddit-01.

Now, either find out your trusty N900’s wifi IP address, or hook it up via USB, in which case its IP address is 192.168.2.15.  Give the command

scp raeddit-01 root@192.168.2.15:

(The default root password is well-known.)  Your binary is now on the phone in the directory /root.  Make sure the phone is connected to the Internet, fire up a terminal on the device, and type

/root/raeddit-01

If you see the current contents of reddit’s front page printed out on the terminal, you’re doing fine:
the output of raeddit-01

First steps into Hildon. So, now we have a very basic reddit client.  Let’s think about making it pretty.

What we want is a series of buttons going down the page that look something like this:

sketchy diagram

Eventually we’ll need to make a custom widget for that, but fortunately there’s a standard Maemo widget called a HildonButton which holds two labels, a title and an optional subtitle, which is close enough to what we want for a basic tutorial.  It looks like this:

A button

We can just stick a bunch of these into a GtkVBox.  But we also want the user to be able to flick through them with her finger, and there’s a specialised Maemo container widget to allow that: it’s called HildonPannableArea. So the GtkVBox will live inside one of those.

So here’s raeddit-02.c (diff to raeddit-01.c), which knows how to put up a window and fill it with buttons.  The buttons don’t go anywhere, but at least we’re getting somewhere!  Compile it, transfer it to the phone, and run it again:

Hildon application showing reddit content

Making the buttons into links. So next we need to make the buttons go to the various sites.  Now, there’s two important things you have to consider when porting or building an app on the N900.  One of them, which we’ve just mentioned, is that sometimes there are widgets which don’t exist on the desktop, because they work in ways which are better adapted to life on a phone.  The other is that there’s a whole ecosystem of programs on the device with which we must play nicely.  One such program is the web browser, and right now that’s exactly the program we need to talk to.

The polite way to ask the browser to show a particular page is by using a DBus call.  Here’s raeddit-03.c (diff to raeddit-02.c), which knows how to do that.  Compile it, transfer it to the phone, and run it again. I would show you a screenshot, but it looks just the same as the last version. And it works.

And now we have a first approximation to the program we wanted, which is at least good enough to call version 0.01!

Where can this go next?

Launcher, including raeddit

  1. The program needs to live in a package, so that it can be installed easily, so that it can have a little icon in the launch menu, and so that it can be uploaded to maemo-extras and perhaps one day to Maemo Select.  We’ll be looking at that next time.
  2. There are lots of things you might want to do with a post on reddit, beyond just viewing the site it links to.  So rather than the buttons going directly to the sites, it would be better if they popped up one of those rather stylish menus saying things like “Go to site”, “Go to comments page”, “Vote up”, “Vote down”, and so on.  (That kind of menu is called a HildonTouchSelector).  We’ll do that the time after next.
  3. Clearly the page should refresh every so often.
  4. The download should really be done asynchronously.
  5. The buttons should really be custom widgets that look more like our mockup.
  6. Many posts on reddit consist only of a picture, and launching the browser for these is probably overkill.  We could do these in-process with a GdkPixbuf.  This should be another option on the popup menu, “View image”, so that people still had the option of using the browser.
  7. Also for picture posts, we could display them inline in the custom widgets, as is done on the website.
  8. Of course, it would be lovely if you could use the client to log in, and vote posts up or down.
  9. Also, the ability to post links would be pretty useful.
  10. There should be an app menu with some useful buttons on it.
  11. The client should support subreddits.
  12. It would be extra fun to have this as a home applet rather than an app.
  13. There should be a way to sort posts by newness, hotness, and so on.  (Yes, I noticed after I wrote it that the current version sorts posts backwards.)
  14. It should be possible to hide posts you’ve already seen.
  15. There should be a “share” button, to share posts you like with other people by email or twitter/identica, and so on.
  16. It would be a nice touch if there were gestures to access the most common options on the popup menu (slide your finger from left to right across a post to open the associated link, and so on.)
  17. I can imagine adding a new addressbook field called “reddit username”, and being able to single-tap open a contact’s reddit user page from their contact information.
  18. The iPhone app has a thing where it goes to a random page if you shake it.  We could do that…
  19. …your idea here…

Let me know where you’d like this series to go in future.  I’m speaking only as a fascinated individual here, and I’d also welcome any corrections you have, as well as any questions about things I left unclear.  If this whets your appetite, you can find out a lot more detail in the official developer guide, or the official porting guide.

My last night in Helsinki

It’s my last night in Helsinki, at least this time around, so I thought I’d do a bit more exploring. Helsinki on the ground never seems to bear much resemblance to the map. Streets seem to vanish and re-materialise again later. Daf had recommended a place called Dong Bei Hu for dinner. After some wandering, I found it, and asked for a table for one. The staff looked me up and down and said they were full; I don’t know whether I was too scruffy to eat there or whether they were actually full, or both. So I was a bit hungry, and wishing someone would hurry up and port Urbanspoon to the N900. (Yes, I know I could have used the website, but I would also have been wishing Urbanspoon covered Finland in the first place. And I had forgotten eat.fi. More fool me.)

But very soon, I found the cathedral, which made up for being hungry:

It’s rather large and very beautiful. I went inside, but it seemed rude to take pictures of that. There was a café in the crypt, but they close at 17:00, for some reason, just when people might be wanting to have dinner there.

On the way back, I went into an Indian restaurant but nobody came to help me and I left after a minute or so. Then I found a Chinese place called Tang Dynasty who were helpful, and I ate there.

After that I came back to the hotel and started coding. I have to be at the airport at five, so I’m planning to stay up. Unfortunately, the fire alarm went off: it wasn’t an actual fire, but I’m on the ninth floor and I’m too sensible to use the lifts, so it was a long walk. The fire brigade came and walked around: they wear black uniforms with the city arms on the back (a crowned boat).

Ladies and gentlemen, this IS Maemo number five

I can finally tell you what I’ve spent the last year working on, and why I’ve been commuting back and forth to Helsinki. It’s a phone that runs Linux (a Debian-based distro called Maemo), and its name is the N900. I’ve been playing with it for months and I love it. Not only is it a phone and a Linux box in your pocket, it also runs robotfindskitten.

Quesadillas and theming

Day: Woke up, went to the gym, came back, worked, and ~plexq made us some rather good quesadillas.  ~Fin made some lovely tag icons for marnanel.org to go along with the existing ones from rosequoll.

Theming: I would like to re-examine the Metacity theme format for GNOME 3.  To this end, I’ve been working on CSS theming for Metacity.  I have a reasonable first pass at it written, and several of the standard themes converted (and several more to do).  But it occurs to me that the people who would like to create themes and the people who would be willing to download and compile several experimental libraries are not necessarily the same.  To this end, I’ve created a wiki to demonstrate the system.  If you write CSS on a page whose name begins with Borders: it will display as the result of rendering that CSS.  There is a tour, which you should take first.

Please feel free to create your own themes, either from scratch or by making copies of the existing ones.  I was going to finish off all the sample themes before announcing this, and also to make a theme wizard that would put together a theme for you from parts (to show how the system is well-adapted to use with editors), but I decided it was better to release early, release often.

Of course, now that I’ve announced this, it’s sure to be vandalised; I’ll try to keep an eye on it, but if you could revert any vandalism you see, I’d appreciate it.  Let me know what you think of the system, either way.

Top fives: Ask me for my top five favourites of anything and I’ll try to give a sensible answer.  So far I’ve been asked for cities, words, puddings, foods, beverages, heresies, books, and Tetris shapes.  Since there are only seven Tetris shapes, that’s rather an easy question: the answer is all of them except “S” and “Z”.

Avvy

When I was about fourteen my parents bought a PC to replace our ageing BBC Micro. There was an adventure game called Leisure Suit Larry which I had heard a lot about and was quite anxious to play. Once I had figured out how to win it, I set about cloning it, and in two years, with the help of my brother Mark who drew all the graphics, I produced a vaguely similar game about a Roman trying to escape Pompeii. It was released eighteen years ago next month. I’m not very proud of the code, though if I find a way of reading 5¼” disks I may open-source it. I’m not very proud of the story, either: I based the story around Roman farces, and though I thought it was quite funny when I was fifteen, the humour strikes me as juvenile and sexist now.

When I had done with that game, I wrote something better. This was Avalot, released sixteen years ago, where approximately the same cast of characters found themselves in the Middle Ages. I had no computer science training at the time, and was unaware of the concept of a virtual machine, but Avalot took several steps towards being a game program written on a general-purpose engine (the engine was called Avalanche). If I had had the opportunity to produce the planned third game of the series, it would presumably have been entirely abstracted. Avalot featured actual puzzles worthy of the name: I’m rather proud of the one about the onion. And I made some attempt to patch up the problems with the story which had been introduced in the first game, as well; Avalot’s wife had a little more to her personality than simply the nagging character from farce. It wasn’t perfect in the least, but it was light years ahead of the original game. Of course, by that time the standard of professional games had moved on, and Avalot looked dated even when it was released.

Both games were released as shareware, and neither made any appreciable amount of money. I think we all had dinner out once on the takings from the first game, and the second game didn’t even make that. But occasionally I still get fanmail.

Sometimes I wonder whether I should resurrect the Avvy franchise as Z-machine games, and whether that would give me a chance to finally fix the immaturity of the original code and of the original humour. I’m not sure, really.