Formatting iTunes Connect Financial Reports
Update 2009-09-23: There is an updated version of the script available. Please see the corresponding blog post and get the newest version of the code from GitHub.
The monthly financial reports Apple provides to iPhone developers in iTunes Connect are plain tab-separated text files. To print those reports for our tax accountants or the taxman, we must apply a little formatting. Since importing text files into a spreadsheet involves some manual work (some columns have to be marked as numeric or text) and I do not need to do further calculations with the data at the moment, I wrote a Ruby script that converts Apple’s text files into printable HTML tables.
To use the script, download all financial reports from iTunes Connect into a folder and run the script as follows:
./financialreport_to_html.rb *.txt
The script will create a .html file with the same name for every file you specify on the command line. You can use the -o option to force it to overwrite existing files.
The script uses a settings file in YAML format to configure things like column headings, column types and which columns to exclude from the formatted page (there’s a lot of columns to fit on one page). Have a look at financialreport_to_html_settings.yaml to see the available options.
The HTML template code, complete with CSS, is directly embedded in the script file. I opted for a simple table that looks good when printed but it should be easy for you to adapt the styling to your needs. The only thing you still have to do manually is to set your printer to landscape format as the page orientation cannot be specified in CSS.
The result looks like this:

Output from financialreport_to_html.rb
Download the script: financialreport_to_html.zipGet the newest version from GitHub. You can do whatever you want with it. I hope you find it useful.
Songtext stopped working

Songtext displaying error message
As of this morning, Songtext is no longer working. LyricWiki, the site Songtext obtained its lyrics from, was required by music publishers to cripple their API in such a way that apps like Songtext no longer have direct access to the lyrics. This effecticely breaks Songtext and many other iPhone lyrics apps that also used LyricWiki as their source.
I am very sorry to all users but at the moment there is nothing I (or LyricWiki) can do about this.
I would like to thank the guys at LyricWiki for their efforts in providing an API in the first place. And special thanks for providing users of Songtext and other apps with a clear error message that should minimize support requests for app developers:
Unfortunately, due to licensing restrictions from some of the major music publishers we can no longer return lyrics through the LyricWiki API (where this application gets some or all of its lyrics).
The lyrics for this song can be found at the following URL: …
(Please note: this is not the fault of the developer who created this application, but is a restriction imposed by music publishers themselves.)
I sincerely hope that the music publishers are working on a solution that would allow for the existence of lyrics apps in the future. The popularity of some of these apps clearly shows that there is a demand. Instead of only crippling third-party solutions, they should provide their own APIs (with their own licensing model if they feel they need to be compensated).
I removed Songtext from the App Store
As of today, Songtext is no longer available as I just removed it from the App Store.
Unfortunately, this also means that there will be no updates for existing users in the foreseeable future. Sorry.
I want to thank everybody who has downloaded Songtext in the last 2 weeks for your support and positive feedback. I hope you still enjoy using the app.
LyricWiki is down, Songtext showing errors
Sorry to all folks who are seeing the “Error loading lyrics” message in Songtext at the moment. LyricWiki, the site Songtext gets the lyrics from, is down this Sunday morning. I hope it will be back up soon and I will keep posting updates here.
I apologize that Songtext does not work at the moment but unfortunately there is nothing I can do about it.
Update July 19th, 2009, 16:00 CEST: LyricWiki is back up again after a downtime of about 5 hours. Songtext should be working again. Sorry again to everybody who got only error messages today.
Lyrics apps for the iPhone: a market overview
Update July 24, 2009: I removed this post because Songtext is no longer available on the App Store.
The Music Player Framework in iPhone SDK 3.0
In version 3.0 of the iPhone SDK, Apple gave us access to the iPod library on the iPhone and and easy-to-use interface to control music playback. In this post, I want to give an overview of these APIs and how I used them in the development of Songtext.
Getting started: MPMusicPlayerController
You need to add MediaPlayer.framework to your target in Xcode and #import <MediaPlayer/MediaPlayer.h>. To control music playback, we use an instance of MPMusicPlayerController. There are two types of music players. The iPodMusicPlayer is a reference to the music player instance used by the iPod app. Any settings you change, such as the shuffle or repeat modes, will be changed in the iPod app, too. If the iPod is playing when your application starts, the music will continue playing and you can access the current song and skip back and forward through the currently active playlist. When your app quits, the music will continue playing. I imagine this mode is very handy for most utility apps that try to improve your music listening experience by interacting with the iPod.
In contrast, applicationMusicPlayer gives you a music player whose settings you can change independently of the iPod app. This is probably the way to go if your app is a game and you want to give the user the ability to choose the background music from their library. In Songtext, we’ll use iPodMusicPlayer because we want to know which song is playing when our app launches:
@property (nonatomic, retain) MPMusicPlayerController *musicPlayer; ... self.musicPlayer = [MPMusicPlayerController iPodMusicPlayer];
The music player uses notifications to inform you about changes of:
- the current song (
MPMusicPlayerControllerNowPlayingItemDidChangeNotification), - the play/paused/stopped state (
MPMusicPlayerControllerPlaybackStateDidChangeNotification), or - the volume (
MPMusicPlayerControllerVolumeDidChangeNotification).
So the next thing you typically do is to register yourself as an observer for the notifications you are interested in, e.g. in viewDidLoad. We want to receive all 3 notifications:
// Register for music player notifications NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; [notificationCenter addObserver:self selector:@selector(handleNowPlayingItemChanged:) name:MPMusicPlayerControllerNowPlayingItemDidChangeNotification object:self.musicPlayer]; [notificationCenter addObserver:self selector:@selector(handlePlaybackStateChanged:) name:MPMusicPlayerControllerPlaybackStateDidChangeNotification object:self.musicPlayer]; [notificationCenter addObserver:self selector:@selector(handleExternalVolumeChanged:) name:MPMusicPlayerControllerVolumeDidChangeNotification object:self.musicPlayer]; [self.musicPlayer beginGeneratingPlaybackNotifications];
There is one other related notification that is sent by the iPod media library when the contents of the library change, e.g. when you sync your device with iTunes. You must listen to this notification if your app creates its playlists that need to be updated after library changes. To do so, register yourself as an observer for MPMediaLibraryDidChangeNotification notifications and call:
[[MPMediaLibrary defaultMediaLibrary] beginGeneratingLibraryChangeNotifications]
The notification handlers are where you update your UI in response to changes in the player’s state:
// When the now playing item changes, update song info labels and artwork display. - (void)handleNowPlayingItemChanged:(id)notification { // Ask the music player for the current song. MPMediaItem *currentItem = self.musicPlayer.nowPlayingItem; // Display the artist, album, and song name for the now-playing media item. // These are all UILabels. self.songLabel.text = [currentItem valueForProperty:MPMediaItemPropertyTitle]; self.artistLabel.text = [currentItem valueForProperty:MPMediaItemPropertyArtist]; self.albumLabel.text = [currentItem valueForProperty:MPMediaItemPropertyAlbumTitle]; // Display album artwork. self.artworkImageView is a UIImageView. CGSize artworkImageViewSize = self.artworkImageView.bounds.size; MPMediaItemArtwork *artwork = [currentItem valueForProperty:MPMediaItemPropertyArtwork]; if (artwork != nil) { self.artworkImageView.image = [artwork imageWithSize:artworkImageViewSize]; } else { self.artworkImageView.image = nil; } } // When the playback state changes, set the play/pause button appropriately. - (void)handlePlaybackStateChanged:(id)notification { MPMusicPlaybackState playbackState = self.musicPlayer.playbackState; if (playbackState == MPMusicPlaybackStatePaused || playbackState == MPMusicPlaybackStateStopped) { [self.playPauseButton setTitle:@"Play" forState:UIControlStateNormal]; } else if (playbackState == MPMusicPlaybackStatePlaying) { [self.playPauseButton setTitle:@"Pause" forState:UIControlStateNormal]; } } // When the volume changes, sync the volume slider - (void)handleExternalVolumeChanged:(id)notification { // self.volumeSlider is a UISlider used to display music volume. // self.musicPlayer.volume ranges from 0.0 to 1.0. [self.volumeSlider setValue:self.musicPlayer.volume animated:YES]; }
Accessing song metadata: MPMediaItem

MPMediaPickerController in single-selection mode. Unfortunately, Apple does not provide context information about the selected song.
A song is represented by an instance of the MPMediaItem class. As you see in the code above, we access the song metadata with the valueForProperty:method. Available properties include pretty much all the data that is available in iTunes: title, artist, album title and artist, genre, composer, duration, track/disc number, album artwork, rating, lyrics, last played date, and play and skip counts. The complete list of properties is available in the documentation. That’s a huge amount of data for all kinds of interesting statistics or organizing apps. I am sure we will see a lot of those on the App Store in the coming months.
No write access to iPod library
Unfortunately, we won’t see apps that require write access to the iPod library anytime soon. The entire MPMediaItem API is read-only at the moment. That is also the reason why Songtext cannot write the lyrics it downloads into the song files themselves to make them available outside the application. I hope Apple gives us write access in a future version of the SDK.
Unreliable access to lyrics
While MPMediaItem provides access to the lyrics of a song stored in the iTunes library, I found this to be unreliable. Songtext checks if a song already has lyrics attached and if so, does not try to download them from the web. Unfortunately, this does not work all the time as sometimes, -[MPMediaItem valueForProperty:MPMediaItemPropertyLyrics] returns nil even if lyrics are present. I was not able to reproduce the exact conditions under which this error occurs. So beware if you rely on this to work properly.
A song selection UI: MPMediaPickerController
Similar to the built-in image picker, Apple provides a complete user interface to select songs from the media library. All we need to do is create an instance of MPMediaPickerController, present it to the user as a modal view controller and implement the MPMediaPickerControllerDelegate protocol:
// MusicPlayerDemoViewController.h @interface MusicPlayerDemoViewController : UIViewController <MPMediaPickerControllerDelegate> { ... } ... // This action should open the media picker - (IBAction)openMediaPicker:(id)sender; @end // MusicPlayerDemoViewController.m - (IBAction)openMediaPicker:(id)sender { MPMediaPickerController *mediaPicker = [[MPMediaPickerController alloc] initWithMediaTypes:MPMediaTypeMusic]; mediaPicker.delegate = self; mediaPicker.allowsPickingMultipleItems = NO; // this is the default [self presentModalViewController:mediaPicker animated:YES]; [mediaPicker release]; } // Media picker delegate methods - (void)mediaPicker: (MPMediaPickerController *)mediaPicker didPickMediaItems:(MPMediaItemCollection *)mediaItemCollection { // We need to dismiss the picker [self dismissModalViewControllerAnimated:YES]; // Assign the selected item(s) to the music player and start playback. [self.musicPlayer stop]; [self.musicPlayer setQueueWithItemCollection:mediaItemCollection]; [self.musicPlayer play]; } - (void)mediaPickerDidCancel:(MPMediaPickerController *)mediaPicker { // User did not select anything // We need to dismiss the picker [self dismissModalViewControllerAnimated:YES]; }
Limitations of the media picker

MPMediaPickerController in multiple-selection mode. This works like the editing of the On-The-Go playlist in the iPod app.
This is all great and simple. The media picker has one huge drawback, though: it does not provide the context from which a song was picked. It is impossible to tell whether the user selected a song from a certain playlist, from an album, or from the Songs tab. All you get back is the single MPMediaItem the user tapped. Therefore, we cannot construct a play queue in the way the iPod does, depending on the context from which the user picked the song. The Next/Previous buttons will not work as expected anymore, and the user would have to pick another song each time the current one ends (the player will just stop at the end of the song). I think this can be very confusing for the user because your app functions differently, depending on whether the user selected a song in the iPod or directly in your app. And that is the reason why Songtext does not have the capability of selecting a new song from inside the app at the moment. Let’s hope Apple improves the media picker in the future.
The media picker also has a multiple selection mode that can be enabled by setting its allowsPickingMultipleItems property to YES. This mode works like the editing of the On-The-Go playlist in the iPod app and can also be quite confusing for the user in my opinion.
Querying the iPod library with MPMediaQuery
If you want to build a custom media picker UI or select songs programmatically without user interaction, you can do so by building queries with MPMediaQuery and MPMediaPropertyPredicate. I will cover these classes in a future post.
Download the demo project
I have prepared a little demo project that implements most of the things I have talked about in this post: Download MusicPlayerDemo.zip. You can do whatever you want with the code, no strings attached.
Announcing Songtext: Lyrics for the iPhone
Yay! Songtext, my first iPhone app, got released last night. Songtext can download the lyrics for the songs you are listening to on your iPhone or iPod touch. It uses the huge database of LyricWiki, containing more than 700,000 songs. The price is $0.99. Check it out at songtextapp.com if you are interested or go right to the the App Store.

Lyrics of the song “On Brevity” by Josh Woodward (License: Creative Commons Attribution)
Blogging about iPhone development
To celebrate the occasion, I am starting this blog about software development. I plan to write about the lessons I learned during the development of Songtext and other projects I am working on. I am going to concentrate on the iPhone SDK, Cocoa, and Objective-C at first but might include more topics in the future.
I also plan to share my experiences as an individual developer for the iPhone platform, so expect posts about the App Store review process, the iPhone SDK community and my sales performance on the App Store.