This weekend at w00tcamp I was part of an ambitious team to try to conquer the world! We would achieve that goal by creating an app called Ladida (or Nostalgify). It would ask you for your birth month and year, and then start playing tracks that were in the top 40 in the month that you turned 17. Because that's the music you have sweet memories of: that first highschool dance, your first kiss while being cheered on by your buddies...
Mark and Kars started by setting up a java-built appengine server that scrapedeveryhit.com and top40.nl (using regex, the horror!), and inserted every top40 single into our own database. Next up was matching a spotify ID with each hit, so the client would have no trouble playing the song. Mark had already performed this trick last year on the Soundmatch team, so that was easy money.
Okay, so now we have a server that can give tracks based on a date input. Time to get cracking on the iPhone app itself. As we're in a team of 5 C# developers and only one of which has any objective-C knowledge, we decided to build on theMonoTouch framework. This makes it possible to create iOS apps using C# in Monodevelop for mac, and would be my responsibility.
As a webdeveloper it took a little getting used to mobile apps. Instead of request-, session and application scope, you just have one scope. Instead of DropDownLists you have UIPickerViews. Animations are set on the whole View instead of on the item you want to animate. But the most difficult of all was getting used to scrolling up-side-down, the Apple way :)
Actually, it wasn't hard at all. In a few hours time I had a custom picker where you can select the month and year you turned 17. When you touched the kick-ass button it went to the appengine server to retrieve 9 songs, the url to their album covers, and of course the spotify id.
I had a bit of trouble displaying the tiles. In HTML its a simple <img src="" />, but in iOS you have to download the bytes of the image and convert them to a UIImage. Here's a little code snippet I used. And this is a synchronous version, it makes the app notoriously slow because it's unresponsive between clicking the button and retrieving all 9 images. But hey, it's a start!
byte[] imageBuffer = SimpleTextInputViewController
.GetImageFromUrl(track.ImageUrl);
NSData imageData = NSData.FromArray(imageBuffer); var img = UIImage.LoadFromData(imageData);
this.SetBackgroundImage(img,UIControlState.Normal);
public static byte[] GetImageFromUrl(string url) { Console.WriteLine("Getting url " + url); Uri address = new Uri(url); HttpWebRequest request = WebRequest.Create(address)
as HttpWebRequest; try { using (HttpWebResponse response = request.GetResponse()
as HttpWebResponse) { var reader = new StreamReader(response.GetResponseStream(),
Encoding.UTF8); byte[] buffer = new byte[16*1024]; using (MemoryStream ms = new MemoryStream()) { int read; while ((read = reader.BaseStream
.Read(buffer, 0, buffer.Length)) > 0) { ms.Write(buffer, 0, read); } return ms.ToArray(); } } } catch ( WebException we ) { Console.WriteLine( we.Message ); } finally { } return null; }
Next up was actually playing the song. We used the libspotify library, which makes it possible to play spotify songs on iOS. Unfortunately the port for monotouch was running on libspotify version 4, and currently it's at version 10. So we spent a full day (out of the 2 days we had!) trying to mix & match the monotouch version with the new iOS version. We ended up being able to login, search, and retrieve playable bytes. Then we got stuck, trying to send the playable bytes to the speakers. Jaap spent a lot of hours on this issue, but eventually came to the conclusion that this wasn't going to work out.
And so the end result of two days work would have been a simple ios music player that couldn't play any music. If it had not been for Kars, who, when we concluded we wouldn't be able to play music, retraced our steps not in MonoTouch but in iOS-native objective c. And he got just about as far as we had gotten, only his app could play music.