Thursday, October 8, 2009

In the remake: EternalWave

As some of you may know (or not), I've been developing a cross-platform media player for a while now, on and off for the past 4 years. However, life gets in the way and during all this time I've only seriously invested maybe 3 months in this project.

The player is (ironically) called EternalWave, even tough it was originally called EternalWave 4. The 4 came from the fact that I had developed previous versions of an audio player that only did one thing: loop trough a song over and over (hence the eternal part). The first version only played wav files and only worked in windows (hence the wave). Version 2 played audio and video trough DirectShow. Version 3 never existed, I skipped the number on purpose since the difference between 2 and 4 was really huge.

After I started using C# heavily, I felt compelled to do a bigger and more complex project, and the idea of a media player fits in that box pretty nicely. I started coding EternalWave 4 in C# as a plugin-based, audio player. Yes, only audio. I managed to write decoders for mp3 and ogg and wav by porting JLayer and JOrbis to C#, and then doing minor modifications. I wrote the wav 'decoder' myself since it only required to parse the RIFF format of wave files.
I managed to code two different audio outputs for windows, through DirectSound and through Win32 API. And then it hit me.

Mono was getting really serious back in those days. What if I could make this media player work in several platforms? Since mono was supposed to work in *nix environments, hypothetically I could have my media player up and running in Linux and Mac OS X in no time.
Easier said than done.

I went for it, and decided to try to run my media player in Ubuntu. Started writing and audio output module trough Alsa, which eventually worked pretty well. However, when I decided to make the player cross-platform, the user interface became a serious problem. Mono didn't have full support for the Windows Forms API, and sometimes had support but behaved differently. Even though I had an skinning system for the user interface, that allowed you to define it in an XML file (pretty much as XAML works), and custom controls in order to control the not so stable behavior in different platforms, I quickly realized that making the UI work was taking most of the development time. After I started using Mac OS X, I tried to run my media player. While it did run, and the core functionality (decoding, etc.) seemed to work, the UI looked horrible.

Conclusion: if you want to make something truly cross-platform you have to rely on technologies known to work on all the platforms you want to target. Windows Forms works flawlessly in windows, but the support in Mono was not the best. I don't blame the mono team for this, they do the best they can with what they have.

So what cross-platform user interface framework could I use for this project? GTK+? GTK#? wxWidgets? (ughh), Qt?

GTK# would had been the reasonable choice, since it has been well developed for C# and has very good documentation. As reasonable as that sounds I dropped it as an option because it makes your application look like a Gnome application, no matter what platform you run it. Not that I have anything against Gnome, but having a media player (a very UI sensitive application) in Windows or OS X looking like a Gnome app would certainly make someone's eyes hurt.

Welcome, Qt.

Oh wait, isn't Qt made in C++? Yes. 
How can you make Qt work in a C# application? It's hell.

So, instead of going straight to coding hell, I decided to port the whole thing to C++. While this sounds as a heavy load, it really isn't. I only have to port the core of the audio player and the plugin management system. There are plenty of audio (and video) decoders written in C/C++ that I can easily use. No need to port the ones I have in C#.

Changing to C++/Qt gives me a lot of benefits and only one serious drawback:
Benefits:
  • Performance boost: minor performance boost, but helps this kind of application as audio and video decoding can become cpu hungry. Also I need to do a lot of memory marshalling/unmarshalling in C# to be able to communicate with low level sound APIs. That is no longer needed if I port to C++.
  • Open Source audio/video decoders: there is a huge amount of those written in C or C++. To be able to use those in C# would have required making a PInvoke layer for each of them to make them usable in the media player. This would have been serious work.
  • Posibility of video output: I can hypotetically use SDL for video output. Hence the player can become an audio/video player instead of an audio-only player.
  • Qt is awesome: Qt is very stable and powerful. Has plenty of features to cover all your UI needs. Has support for almost everything your app may need to do. And it uses the platform's look and feel whenever possible.

Drawbacks:
  • It's C++: Memory leaks, dangling references, multiple class inheritance, buffer overflows, there are no interfaces, no formal delegates, compiler errors are sometimes impossible to understand, ... The complaint list can keep going.
In my opinion, the pros outweigh the cons. Besides Qt makes the cons a bit more bearable with its object model.

So here we go, on for the development (again) of one of the most challenging but fun projects I've had the pleasure to develop. I learned a lot doing this in C#, and I think I'll learn even more doing it with Qt/C++, especially because doing it this way, there is the posibility that I will open the source of it.

Wednesday, September 30, 2009

DotDash: A simple (and yet to be finished) game for iPod/iPhone


So... i will start this blog's first post with a description of my first ever slightly serious iPhone application. It's that classic game that you are your friends used to play on a piece of paper whenever you where stuck in a boring and long class.  Since i'm not sure what the official name of the game is, I will just call it DotDash.


The game is for two players and the objective here is to make more squares that your opponent, you make squares by drawing lines between the dots. Players switch turns unless someone makes a square. If a player makes a square, that player plays again.


When there are no more possible lines to be drawn, the player with the most squares wins.


Yeah I know, this is not going to be the next best seller in the App Store, but I think I'm off for a good start at iPhone OS development. Doing this game gave me a hands on exercise on most of the basic things that an iPhone OS application has to do: Cocoa touch interfaces, touch interaction, 2D drawing, saving and loading settings and basic animations. It also provide a self-learning experience in Objective-C programming (this is the first time ever I program in this language).


The game is almost done minor few details (when the game finishes there is no feedback at all about that fact), but those will be covered very soon.


So for those who are curious about iPhone OS development, I say you go for it and try to develop a simple project like this one in the beginning, so you can get an idea of how the platform feels like. Who knows, you might be developing something out of curiosity that may bring major bucks later.