Hostingheaderbarlogoj
Join InMotion Hosting for $3.49/mo & get a year on Tuts+ FREE (worth $180). Start today.
Advertisement

iOS SDK: Music Library Access

by
Gift

Want a free year on Tuts+ (worth $180)? Start an InMotion Hosting plan for $3.49/mo.

With music library access your applications can incorporate the songs, audio books, and podcast collections of your users. This functionality can be used to enhance gameplay by allowing users to play their own soundtrack, build custom media-player applications, and more!

NOTE: In order to test this functionality you will need a physical iOS device and will need to be a member of the paid iOS developer program.

Step 1: Creating the Project

Open Xcode and select “Create a new Xcode project”. Select “view-based application” and click “next”. Enter a name for your project (I called mine “Music”), enter your company identifier, make sure you select iPhone for device family, and then click “next”. Choose a place to save your project and click “create”.

New Project

Step 2: Import the MediaPlayer Framework

In the navigator area of Xcode 4, select the project name (in our case “Music”). Next, select the current target (“Music” here again), and then select the “Build Phases” tab. Expand the “Link Binary With Libraries” option, and then click the “+” button to add a new framework. Type “MediaPlayer″ into the search box, and select the MediaPlayer.framework option that appears in the list. Click “Add” to include this framework in the linking phase of your project.

Figure

Now that you have added the media player framework into your project, you need to import that framework into the view controller that will use the iPod
library. Go to the MusicViewController.h file and insert the following line of code below the UIKit #import line:

#import <UIKit/UIKit.h>
#import <MediaPlayer/MediaPlayer.h>

Step 3: Importing the Project Images

Download the source code and drag the images map to your project. Make sure that the checkbox by Copy item into destination group’s folder (if needed) is checked. This map contains the images we will use in this app.

Adding Files

Step 4: Designing the Interface

In the “Music” folder in the “Project Navigator” click on MusicViewController.xib.

Drag a UIImageView from the library to the view. Make sure the utilities window is shown and go to the Size Inspector. Set both the width and height to 200, the x-coordinate to 60 and the y-coordinate to 20. This image view will show the songs artwork.

Now drag a UISlider to the view and arrange it with the blue guide lines to the bottom of the view. Also make it a bit wider, so it uses the entire width of the view between the two blue guidelines. We will use this slider to adjust the volume.

Now drag 4 UIButtons to the view. Drag the first one under the image view and set its title to “Show Media Picker”. This one will do just what the text says. The other three buttons will be the control buttons. Select the other three buttons and go to the Attributes Inspector. Set the type to Custom and set the image of the buttons respectively to PreviousButton.png, PlayButton.png and NextButton.png. Arrange the buttons like below.

At last, drag three UILabels to the view. Delete the text of all the labels and arrange them like below (I added some text, so you can see where the labels are. You won’t need to add this text). These labels will show some information about the currently playing song.

Interface

Step 5: Making the IB Connections

Now that we have designed out interface, we can make the connections. Click the middle button of the editor to show the assistant editor .

Assistant Editor

Click the image view and CTRL-drag to the interface. A pop-up will show. Enter the text “artworkImageView” for name and then click “connect.”

Connection

Now Click the slider and connect it the same way, but name it “volumeSlider”. CTRL-drag again from the slider to the interface, but this time under the curly braces. Set the connection to Action instead of Outlet. Enter “volumeChanged” for the name and make sure the event is Value Changed and click “connect”.

These 4 buttons also need actions. Connect them the same way the slider action was connected. Name the actions as follows:

  • Show Media Picker button: showMediaPicker
  • Previous button: previousSong
  • Play button: playPause
  • Next button: nextSong

The play button also needs an outlet. Connect it the same way we connected the outlet for the image view, but name it “playPauseButton”.

At last we need to create the outlets for the labels. Connect them again the same way we connected the image view outlet. Name the first label “titleLabel”, the second label “artistLabel” and the last label “albumLabel”.

Now the code for the MusicViewController.h file should read as follows:

#import <UIKit/UIKit.h>
#import <MediaPlayer/MediaPlayer.h>

@interface MusicTestViewController : UIViewController {

 IBOutlet UIImageView *artworkImageView;
 IBOutlet UISlider *volumeSlider;
 IBOutlet UIButton *playPauseButton;

 IBOutlet UILabel *titleLabel;
 IBOutlet UILabel *artistLabel;
 IBOutlet UILabel *albumLabel;

}
- (IBAction)volumeChanged:(id)sender;
- (IBAction)showMediaPicker:(id)sender;
- (IBAction)previousSong:(id)sender;
- (IBAction)playPause:(id)sender;
- (IBAction)nextSong:(id)sender;

@end

Build and Run the code to make sure that the app runs well. The app only shows the interface we just created, but the buttons won’t work.

Step 6: Creating a Music Player Controller

Go to the MusicViewController.h file and modify the code to read as follows:

#import <UIKit/UIKit.h>
#import <MediaPlayer/MediaPlayer.h>

@interface MusicTestViewController : UIViewController <MPMediaPickerControllerDelegate> {

    IBOutlet UIImageView *artworkImageView;
    IBOutlet UISlider *volumeSlider;
    IBOutlet UIButton *playPauseButton;

    IBOutlet UILabel *titleLabel;
    IBOutlet UILabel *artistLabel;
    IBOutlet UILabel *albumLabel;

    MPMusicPlayerController *musicPlayer;

}
@property (nonatomic, retain) MPMusicPlayerController *musicPlayer;

- (IBAction)volumeChanged:(id)sender;
- (IBAction)showMediaPicker:(id)sender;
- (IBAction)previousSong:(id)sender;
- (IBAction)playPause:(id)sender;
- (IBAction)nextSong:(id)sender;

- (void) registerMediaPlayerNotifications;

@end

As you can see we added the MPMediaPickerControllerDelegate and created a MPMusicPickerController. We also added the method registerMediaPlayerNotifications for registering notifications from the media player.

Now go to the MusicViewController.m file and synthesize the musicPlayer by adding the following code under the @implementation :

@synthesize musicPlayer;

We also need to release it in the dealloc and viewDidUnload method with the following code:

[musicPlayer release];

Now go to the viewDidLoad method. Uncomment it and add the following code under [super viewDidLoad];

musicPlayer = [MPMusicPlayerController iPodMusicPlayer];

Here we set our music player controller to an iPodMusicPlayer. This means that our app shares the iPod state and if we quit our app the music will continue playing. The applicationMusicPlayer is the other type. This music player plays the music locally within your app. Your music player can have a different now playing item than the built-in iPod app. When you quit the app, the music stops playing.

Step 7: Updating the UI Upon Load

Add the following code to the viewDidLoad method:

    [volumeSlider setValue:[musicPlayer volume]];

	if ([musicPlayer playbackState] == MPMusicPlaybackStatePlaying) {

        [playPauseButton setImage:[UIImage imageNamed:@"pauseButton.png"] forState:UIControlStateNormal];

    } else {

        [playPauseButton setImage:[UIImage imageNamed:@"playButton.png"] forState:UIControlStateNormal];
    }

First, we set the current value of the slider to the music player’s current volume. Volume is a value between 0 and 1. If the volume is 0 there is no sound and when the volume is 1, the volume is on his maximum. After that we check it the music player is playing something. If it’s playing, we set the image of the playPauseButton to the pauseButton image and when it isn’t playing we set the image of the playPauseButton to the playButton image.

Step 8: Register the MediaPlayer Notifications

Add the following code to the viewDidLoad method:

[self registerMediaPlayerNotifications];

This line will call the registerMediaPlayerNotifications method where we will register three observers for the media player notifications. Add the following code under the viewDidLoad method:

- (void) registerMediaPlayerNotifications
{
    NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];

	[notificationCenter addObserver: self
						   selector: @selector (handle_NowPlayingItemChanged:)
							   name: MPMusicPlayerControllerNowPlayingItemDidChangeNotification
							 object: musicPlayer];

	[notificationCenter addObserver: self
						   selector: @selector (handle_PlaybackStateChanged:)
							   name: MPMusicPlayerControllerPlaybackStateDidChangeNotification
							 object: musicPlayer];

    [notificationCenter addObserver: self
						   selector: @selector (handle_VolumeChanged:)
							   name: MPMusicPlayerControllerVolumeDidChangeNotification
							 object: musicPlayer];

	[musicPlayer beginGeneratingPlaybackNotifications];
}

Here we register three observers for the media player notifications. The first one is for the MPMusicPlayerControllerNowPlayingItemDidChangeNotification. We will use this to update the current media item information. The second one is for the MPMusicPlayerControllerPlaybackStateDidChangeNotification, we also use this one to update our UI. The third and last one is for the MPMusicPlayerControllerVolumeDidChangeNotification, we will use this one to update the current value of our slider.

Whenever you register an observer, you should also be sure to remove it in the viewDidUnload and the dealloc methods. So add the following code to both these methods:

    [[NSNotificationCenter defaultCenter] removeObserver: self
													name: MPMusicPlayerControllerNowPlayingItemDidChangeNotification
												  object: musicPlayer];

	[[NSNotificationCenter defaultCenter] removeObserver: self
													name: MPMusicPlayerControllerPlaybackStateDidChangeNotification
												  object: musicPlayer];

    [[NSNotificationCenter defaultCenter] removeObserver: self
													name: MPMusicPlayerControllerVolumeDidChangeNotification
												  object: musicPlayer];

	[musicPlayer endGeneratingPlaybackNotifications];

Add the following code under the registerMediaPlayerNotifications method:

- (void) handle_NowPlayingItemChanged: (id) notification
{
   	MPMediaItem *currentItem = [musicPlayer nowPlayingItem];
	UIImage *artworkImage = [UIImage imageNamed:@"noArtworkImage.png"];
	MPMediaItemArtwork *artwork = [currentItem valueForProperty: MPMediaItemPropertyArtwork];

	if (artwork) {
		artworkImage = [artwork imageWithSize: CGSizeMake (200, 200)];
	}

    [artworkImageView setImage:artworkImage];

    NSString *titleString = [currentItem valueForProperty:MPMediaItemPropertyTitle];
    if (titleString) {
        titleLabel.text = [NSString stringWithFormat:@"Title: %@",titleString];
    } else {
        titleLabel.text = @"Title: Unknown title";
    }

    NSString *artistString = [currentItem valueForProperty:MPMediaItemPropertyArtist];
    if (artistString) {
        artistLabel.text = [NSString stringWithFormat:@"Artist: %@",artistString];
    } else {
        artistLabel.text = @"Artist: Unknown artist";
    }

    NSString *albumString = [currentItem valueForProperty:MPMediaItemPropertyAlbumTitle];
    if (albumString) {
        albumLabel.text = [NSString stringWithFormat:@"Album: %@",albumString];
    } else {
        albumLabel.text = @"Album: Unknown album";
    }

}

This method will respond to the MPMusicPlayerControllerNowPlayingItemDidChangeNotification: notification. First we create a MPMediaItem and set it to the nowPlayingItem. Then we create a UIImage called artworkImage. For default we set the image to the noArtworkImage. Then we create an MPMediaItemArtwork object which stores the artwork of the current item. If there is artwork, we set the artworkImage to the artwork. Finally, we set the artworkImageView image to the artworkImage.

Then we create an NSString with stores the title of the currentItem. Again, we check if the currentItem has a title. If it has a title we set the tittleLabel to that title. If the currentItem doesn’t have a title, we set the title to “unknown”. We do the same with the artist and album.

We only used the artwork, title, artist, and album properties here, but there are many more properties like lyrics, rating and composer.

Add the following code under the handle_NowPlayingItemChanged: method:

- (void) handle_PlaybackStateChanged: (id) notification
{
    MPMusicPlaybackState playbackState = [musicPlayer playbackState];

	if (playbackState == MPMusicPlaybackStatePaused) {
        [playPauseButton setImage:[UIImage imageNamed:@"playButton.png"] forState:UIControlStateNormal];

	} else if (playbackState == MPMusicPlaybackStatePlaying) {
        [playPauseButton setImage:[UIImage imageNamed:@"pauseButton.png"] forState:UIControlStateNormal];

	} else if (playbackState == MPMusicPlaybackStateStopped) {

        [playPauseButton setImage:[UIImage imageNamed:@"playButton.png"] forState:UIControlStateNormal];
		[musicPlayer stop];

	}

}

This method will respond to the MPMusicPlayerControllerPlaybackStateDidChangeNotification: notification. Here we check the state of the music player and update the image of the playPauseButton. As you can see we stop the music player if its state is MPMusicPlaybackStateStopped. We do this to ensure that the music player will play its queue from the start.

At last, add the following code under the handle_PlaybackStateChanged: method:

- (void) handle_VolumeChanged: (id) notification
{
    [volumeSlider setValue:[musicPlayer volume]];
}

This method will respond to the MPMusicPlayerControllerVolumeDidChangeNotification: notification. Here we update the volume sliders value to the music player’s volume. We do this because we can also adjust the volume with the hardware buttons.

Step 9: Making the controls work

Go to the volumeChanged: action and modify the code to read as follows:

- (IBAction)volumeChanged:(id)sender
{
    [musicPlayer setVolume:[volumeSlider value]];
}

Here we set the volume of the music player to the value of the slider.

Now go to the playPause: action and modify the code to read as follows:

- (IBAction)playPause:(id)sender
{
    if ([musicPlayer playbackState] == MPMusicPlaybackStatePlaying) {
        [musicPlayer pause];

    } else {
        [musicPlayer play];

    }
}

First we check if the music player is playing. If it’s playing we will pause the music player. If the music isn’t playing, we start playing the music.

Now go to the previousSong: action and modify the code to read as follows:

- (IBAction)previousSong:(id)sender
{
    [musicPlayer skipToPreviousItem];
}

Here we let the music player skip to the previous item.

At last, go to the nextSong: action and modify the code to read as follows:

- (IBAction)nextSong:(id)sender
{
    [musicPlayer skipToNextItem];
}

Here we let the music player skip to the next item.

Step 10: Showing the Media Picker

The last thing we need to do is to show the media picker and play a song if the user picked one or more songs. Go to the showMediaPicker: action and modify the code to read as follows:

- (IBAction)showMediaPicker:(id)sender
{
    MPMediaPickerController *mediaPicker = [[MPMediaPickerController alloc] initWithMediaTypes: MPMediaTypeAny];

    mediaPicker.delegate = self;
    mediaPicker.allowsPickingMultipleItems = YES;
    mediaPicker.prompt = @"Select songs to play";

    [self presentModalViewController:mediaPicker animated:YES];
    [mediaPicker release];
}

First we create a media picker controller and set its delegate to self. We also allow the user to pick multiple items. The prompt is the text that will be displayed when the media picker shows. I set the prompt to “select songs to play”. Then we show the media picker and release it.

Add the following code under the showMediaPicker: action:

- (void) mediaPicker: (MPMediaPickerController *) mediaPicker didPickMediaItems: (MPMediaItemCollection *) mediaItemCollection
{
    if (mediaItemCollection) {

        [musicPlayer setQueueWithItemCollection: mediaItemCollection];
        [musicPlayer play];
    }

	[self dismissModalViewControllerAnimated: YES];
}

- (void) mediaPickerDidCancel: (MPMediaPickerController *) mediaPicker
{
	[self dismissModalViewControllerAnimated: YES];
}

The first method is called when the user picks a song. In this method we check if there is media item collection and if there is a media item collection we set the music player’s queue to that media item collection and start playing. We always dismiss the media picker controller. The second method only dismisses the media player controller.
Click Build and Run to test the application. You can pick a song if you press the Show Media Picker button. You see the title, artist, album and artwork of the current song. If you adjust the volume with the hardware buttons you can see the slider changing.

Wrap Up

Thanks for reading this tutorial about iPod library access! If you have questions or comments on this tutorial, leave them in the comments section below!

Advertisement