Cross Platform thoughts through the lense of Banshee

Banshee running on OS X 10.5
Banshee 1.3.2 on Mac OS X 10.5

A huge amount of thanks goes to Eoin Hennessy for all of his efforts to bring Banshee to the Mac. Eoin singlehandedly fixed cross platform bugs in our core, worked out some kinks in the build, and implemented a Mac OS X platform backend to provide tight integration with the OS (i.e. the menu bar).

So how do I get it?

On Friday we will release Banshee 1.3.3, the last preview/developer release before we officially bless 1.4 as the new stable series in a couple of weeks.

As Miguel mentioned, we will be releasing for the Mac from here on. That means that along side our source code tarballs, RPMs for openSUSE, and packages published through other distributions, we will have a .dmg available to download.

If you are courageous, you can try to build Banshee on OS X today. However, our trunk does not yet run. Eoin has done all of his work in github, and while this branch runs, it’s slightly outdated, and does not use the new build environment I wrote this weekend.

Eoin is in the process of extracting patches that we will merge this week into trunk. These patches include the fixes to core, and the OS X integration.

Banshee running on OS X 10.5
More bling, before I ramble on about technical things and get teary-eyed and nostalgic

How does this cross platform stuff work?

Banshee is designed in a very modular way. We have a fairly small core, which is completely platform agnostic. It uses only ECMA/OSP .NET APIs and APIs of libraries which are themselves cross platform and open source (Mono.Addins, NDesk.DBus, Cairo, GTK, etc).

Additionally, all real features are designed as extensions: the Play Queue, video playback, the notification area, Last.FM, and so on. This means that we can easily pick and choose features by adding or removing assemblies from a package.

Finally, anything requiring a platform specific implementation is abstracted into an agnostic factory/interface, and implementations are loaded as extensions.

Cross platform frameworks give you the 90%, but it’s really the 10% that matters

It’s virtually impossible to write a cross platform application that does not suck if you just stick to what a single framework provides. By this I mean if we used only features in .NET or if a Java application used only features in the Java framework, the user experience would feel isolated and sandboxed.

  • In GNOME this means using GConf to store settings and working with DBus services like GNOME Settings Daemon. We interact with the screensaver, we support multimedia keys, integrate with Brasero for CD burning, and so on.

  • In the general UNIX world (Linux and BSD/OS X), we have a POSIX IO backend that performs much better than the System.IO .NET backend.

  • In Linux we have the HAL hardware backend (which I like to think of as HALAL, but don’t read too far into that).

  • On OS X we integrate with the dock and the system menu bar.

Okay, but what about Windows?

Ah, right. Windows. There’s one tiny little drawback to making a media player written in C# cross platform. Namely, we require GStreamer on all three platforms, and in turn we have a small library, libbanshee, written in C. Of course this pain is more than eased by the incredible power and functionality that GStreamer offers.

The truth is, I know next to nothing about Windows, and I find it incredibly frustrating to work in that environment. I am getting close however to getting a build of libbanshee on Windows. With this piece in place, we’ll be able to release on WIndows.

Currently the goal is that we’ll always distribute libbanshee as a binary on Windows, but the rest of Banshee can be built using “F5” in Visual Studio. This will be very interesting as it opens up Banshee to a whole new world of contributors.

Google Chrome has seen an incredible amount of contribution from external contributors simply because the source can be downloaded, opened with Visual Studio, and compiled. Users can tweak some code, and immediately see the results. This is where we want to be – Linux, Mac, and Windows.

The End Result

What is important with all of this cross platform work is simple: infiltrate the proprietary platforms, attract users and developers to free software, and grow the open source ecosystem. Ultimately, we’d like to think this will help Linux adoption. Applications are the key, not the platforms.

Banshee on Mac OS X is symbolic to me. It marks a period in our project where we step out of the realm of our comfortable and lovable GNOME community and into different communities, creating and bridging through the shared goal of open and free software. Users unite!

Finally, I’d again like to thank Eoin for his great efforts with our code, Imendio for their great work on GTK for OS X, the Mono team for the solid 2.0 release, and the GStreamer community for the best multimedia framework an application developer could ask for.

Useful tidbit for MonoDevelop users

If you are developing a project in MonoDevelop and your solutions/projects are in the old MonoDevelop 1.0 format (mds/mdp files), you’ll probably want to convert them at some point to the new VisualStudio 2005/2008 formats that will be the default format in upcoming versions of MonoDevelop (2.0).

They are well supported in at least MonoDevelop trunk right now, and switching your MonoDevelop 1.0 project layout to VisualStudio’s layout means you can more easily develop on both Linux and Windows. This is a good thing for us working on Banshee (hint, hint).

MonoDevelop makes the conversion part fairly straight forward. Select your top level solution, right click it, and then Tools->Export. Select either VisualStudio 2005 or 2008. We’re sticking with 2005 for now in Banshee since we only care about C# 2.0 at the moment. Choose an export directory, it’ll be temporary.

Unfortunately, it gets a little hairy here, and I wish MonoDevelop had some sort of “convert in place” option (hint, hint, MD team). Open a terminal, change to the directory MonoDevelop exported the project hierarchy to, and run this:

PRJ_DIR=$HOME/svn/banshee; for x in $(find . -iregex '.*cs?proj$' \ 
    -o -name '*.sln'); do cp $x $PRJ_DIR/$(dirname $x); done;

Set PRJ_DIR to the directory of your project containing the project or solution file you originally exported.

This will ensure the new VisualStudio project/solution files are overlayed properly. Now you’ll have to add them to your version control and remove the old mdp/mds files.

$ find . -iregex .*.cs?proj$ -o -iregex .*.sln$ | xargs svn add
$ find . -iregex .*.mds$ -o -iregex .*.mdp$ | xargs svn delete

Hurray for having both runtime and build time environments cross platform! We’re looking forward to having contributors from both camps in the near future. More on this to come!

Update: Lluis points out that MD can in fact convert in place if you set the output directory to be the original directory. This seems too obvious :-).