This post is actually rather after the fact. I’ve been super busy, and my blogging tends to fall way, way behind when that happens. But I wanted to tell people about plans for Amarok Mobile, where things stand now, and what needs to be done. (And how you could help!)

First off, I need to give a big shout-out to Nokia. A while back, they donated ten n900 devices to KDE developers who submitted proposals describing what they would work on. I was one of the lucky winners, and this provided both the motivation and means to start working on an Amarok Mobile.

I actually was not initially supposed to use this for Amarok Mobile development — I had sumitted a proposal to bring functionality similar to the beloved* Popup Dropper into a library for Maemo programs. Problem: having never used Maemo before, I didn’t realize it had longpress functionality (my previous phone was an iPhone).

So, not wanting to reinvent the wheel needlessely, I instead decided to start working on exactly what everyone had assumed/thought/wanted me to be working on when they heard I was one of the n900 recipients: Amarok Mobile.

Below is a record of some of the work that has been done, and that remains to be done.

Core work

In large part due to its very rapid pace of development, Amarok’s code base has had a habit of growing haphazardly, and one of the results has been a lot of incestuous code…things coupled when they really shouldn’t be, code being referenced and implemented all over the place, and so on.

As a result, one of the first things I did was to work on separating out code that provide core functionality — things like podcasts, playlists, our metadata system, collections, and more — and boil them down to the basics. The rule for the core library is: no GUI code, and nothing inside core may reference any files outside of core. The point is that core should comprise the essence of Amarok, and much of what’s left are the possibly platform-specific implementations. In addition, I standardized namespaces for the parts of core, standardized include headers (which makes it much easier to handle file moves later, since they are fully-pathed from the top level source directory), and had absolutely countless compilation cycles. It was an absolute fsckload of work.

However, I think it paid off. We now have, inside src/, a core/ directory and a core-impl/ directory. If we studiously keep core/ separated, it will provide an excellent base on which alternative GUIs and implementations of those core classes can be built. In addition, more things will be moved there, or at least the paradigm will continue being followed; for instance, our great contributor Erik Hovland has been making progress on separating out the GUI layer from our Services framework so that we can have the great services like Ampache and Magnatune and Last.fm and so on be relatively easily activated on other platforms.

SQL

Amarok 2 currently uses MySQL exclusively, allowing you to either use a MySQL server or libmysqld for an embedded database. This has pros and cons, but the really relevant pro is the huge speed gains we get over SQLite. (Before people comment about how we must be doing something wrong: we’re not the only project that has seen serious speed problems with SQLite — I know that Quassel has had similar issues; and if you’re convinced that it’s our schema or some other such thing, you’re welcome to help us improve it. Many others have made this claim, and none of them have ever taken our invitation to actually help us improve things.)

So the obvious question comes up: what about Amarok Mobile? I’m not sure how realistic it is to expect that we can get libmysqld running efficiently on the n900, especially given its memory limitations. At the same time, SQLite is readily available. But, we want to avoid writing tons of custom code.

As it turns out Quassel has a really great storage abstraction using QtSql, and they use both SQLite and PostgreSQL. So, if we copied their really nice approach, we could maybe support SQLite with Amarok Mobile while reducing developer effort to a minimum (since none of us are SQL experts).

One of the big problems we’ve had with QtSql before is that the QMYSQL plugin can support libmysqld (except that it can’t; more on that in a second), but in one of the most boneheaded software design choices I’ve ever seen in my life, MySQL determines whether you’re connecting to a server or an embedded server based on which library your program *links* to. This is not a runtime option. Wut.

So — the obvious option is to bring to Qt what we do in Amarok — instead of having a QMYSQL driver that has to link to one of the other, have a QMYSQL driver linking to the server libraries and a QMYSQLE driver linking to the embedded libraries, and let application developers choose one or both. I began working on this, and have been successful in building both drivers, and have high hopes I can get it included into Qt 4.8 (there’s necessarily a lot of code duplication, so I’ll have to see what they say about that…I may be able to abstract some of it into shared functions, but anywhere that mysql in any case was used, I had to replace with mysqle).

Now, I said that it can’t actually support libmysqld. The reason is that you pass in options for the embedded server upon library init — but QtSql *always* initializes the library with null options. Which means, among other things, that it will use /var/lib/mysql (or whatever your compiled-in default is) for its database directory, which normally means that if you’re not the root user, you can’t actually do anything because it can’t create its files. Whoops.

I can’t break ABI or API, so I’ve been wondering what to do about this — some of the Qt guys suggested I create a new SQL framework with these drivers in it, but I don’t think that’s a great option. Instead, I plan on creating a new connection option (see the table here). Normally these are basically mapped to MySQL options and used like this:

db.setConnectOptions("CLIENT_SSL=1;CLIENT_IGNORE_SPACE=1");

This connection option will not be mapped directly to a MySQL option, but will instead take a delimited list of options, something like this:

db.setConnectOptions("CLIENT_SSL=1;CLIENT_IGNORE_SPACE=1;MYSQLD_INIT_OPTIONS=myoption1=myvalue1;;myoption2=myvalue2;;myoption3=myvalue3");

This would let you pass arbitrary options, and this list would be split and each of the options would be passed into library initialization. It’s API/ABI compatible and relatively straightforward, so it’s the best thing I can think of right now.

Future work

The next steps are to finish the QtSql modifications and get those submitted upstream. Maemo right now has Qt 4.6, but *eventually* will have 4.8…so when 4.8 is coming around, if my QtSql changes are in there, Amarok can try migrating to QtSql; to finish services GUI separation and separation of other parts of Amarok (like AmarokURLs), and to begin writing a GUI, ideally using the Qt Kinetic declarative UI library — when you’re starting from scratch, you might as well do it right. Fortunately some of these tasks will be much easier now that Qt is fully supported/included in the proper locations with the n900 PR 1.2 firmware release.

My time has become incredibly limited in the past month, so if you have time and are interested in helping, join us!

* Okay, I know one person that really, really hates it. And a lot of people that never really realized it was there. But a lot like it!