Pretty image
The iPad comes with a bunch of new programming APIs, designed to support its revolutionary new interface. Here’s a look at just one—the ability to embed movies into your application.

Anyone who has held an iPad in their hands knows that it’s so much more than a big iPod touch. The additional real estate comes with support for custom gestures, enhanced input, sophisticated text processing, and so much more. And yet, at its core, the iPad is designed for media consumption—the large, in-hand screen is perfect for graphic display, especially video. With an iPhone, you can only display video in a full-screen viewer, while the iPad’s SDK allows you to build video right into your applications and fully customize the user experience around it. The SDK also exposes the state of the player, so you can directly control the video and coordinate its playback with the rest of your application.

In this article, we’re going to scratch the surface of the movie player’s capabilities by embedding it in an application. On the real device you can overlay other views on top of it, create navigational thumbnails, and stream content. If you’ve used video player frameworks in the past, you’ve probably found them to be difficult to work with, but using Apple’s new framework, we’ll have a sophisticated player up and running in no time. Note: this article is adapted from our new book, iPad Programming: a Quick-Start Guide for iPhone Developers. Both the book and this article assume you’re already comfortable with developing for the iPhone.

Before we start, let’s save us all some time. We already have the basic iPad project code written for you, so just download the code from the book and navigate to the movieplayer/MoviePlayer1 folder.

Set Up a View for the Movie

Go ahead and open the project in the downloaded folder, and you’ll find that we’ve added a video to the Resources directory called Movie.mp4. We’ve also added the MediaPlayer.framework to your frameworks folder.

First, let’s focus on getting a MPMoviePlayerController instantiated—this class manages all the details of playback and gives you a view that you can add to your own view hierarchy to display video. The MPMoviePlayerController can also display our video content full-screen.

Let’s start this process by opening the MoviePlayerViewController.xib Nib file in Interface Builder and adding a view that can be used to hold the MPMoviePlayerController’s video. (Just to make sure we have this straight: the MoviePlayerViewController is the main view controller for our application; the MPMoviePlayerController is the iPhone OS 3.2 controller for managing video playback.) Begin by selecting the MoviePlayerViewController’s main view and resetting its background color to solid black. Then drag a UIView object from the Interface Builder Library into the view. You’ll want to use the Size tab of the Inspector to configure your new UIView. Make sure to copy the size and autosizing constraints in your version.

Now we need to create an outlet to this new view in our MoviePlayerViewController header file, like this:

 @interface MoviePlayerViewController : UIViewController {
  UIView *viewForMovie;
*   MPMoviePlayerController *player;
 }
 @end

Here we’ve defined a UIView named viewForMovie and also declared it as a property that is an IBOutlet. Don’t forget to also add the synthesize directive to the MoviePlayer1ViewController.m file:

 @synthesize player;

Now let’s wire things up by going back to the MoviePlayerViewController.xib Nib file in Interface Builder. Connect the viewForMovie IBOutlet we just declared to the UIView. To do that, control-click the Nib file’s File’s Owner object and drag to the new view. When the connection popup appears, choose viewForMovie.

Meet the MPMoviePlayerController

With the Interface Builder work out of the way, let’s focus on code. We’re going to add an instance of the MPMoviePlayerController class by declaring it in the MoviePlayerViewController.h header file. First, we need to import the movie player’s MPMoviePlayerController.h file, and then add a declaration for the player; we’ll also go ahead and declare the player as a property. While we’re here, let’s also add a declaration for a method named movieURL (we’ll come back to this shortly).

 #import <UIKit/UIKit.h>
*  #import <MediaPlayer/MPMoviePlayerController.h>
 
 @interface MoviePlayerViewController : UIViewController {
  UIView *viewForMovie;
*   MPMoviePlayerController *player;
 }
 
 @property (nonatomic, retain) IBOutlet UIView *viewForMovie;
*  @property (nonatomic, retain) MPMoviePlayerController *player;
 
*  -(NSURL *)movieURL;
 @end

Let’s take a look at the MoviePlayerViewController.m implementation file. We’re going to start in the viewDidLoad method and instantiate the MPMoviePlayerController there. Let’s add the code and then walk through it:

 - (void)viewDidLoad {
  [super viewDidLoad];
 
  self.player = [[MPMoviePlayerController alloc] init];
  self.player.contentURL = [self movieURL];
 }

Here, we’ve first alloc’d and init’d the movie controller and assigned it to our player property. Next we assigned a content URL to the player—this is the location of the video content we sent the player to play back, which can be a local file in the bundle or a network-based URL. For now, we’re going to use a local file for our video content. Let’s take a quick detour to look at the movieURL method that constructs a file-based URL to the video content in the bundle:

 -(NSURL *)movieURL
 {
  NSBundle *bundle = [NSBundle mainBundle];
  NSString *moviePath =
  [bundle
  pathForResource:@"Century3min"
  ofType:@"mov"];
  if (moviePath) {
  return [NSURL fileURLWithPath:moviePath];
  } else {
  return nil;
  }
 }

If you’ve ever constructed a URL to an image or other resource in the bundle, this code should look familiar: here we obtain a reference to the bundle, then construct a URL to our movie, wrap it in an NSURL object, and return it. In the book we’ll return to this code and construct some network-based URLs to stream content to the iPad.

But now, back from our detour, we’re going to look at one of the most important concepts in this article: the use of the MPMoviePlayerController’s video property. As we mentioned earlier, the player controller maintains a special view that can be added as a subview to any of your views to display video content. Treat this view with kid gloves—although there are some interesting reasons to add our own subviews to the player’s view, this is in general an opaque object under the control of the player, and should be treated that way.

  - (void)viewDidLoad {
  [super viewDidLoad];
 
  self.player = [[MPMoviePlayerController alloc] init];
  self.player.contentURL = [self movieURL];
 
*   self.player.view.frame = self.viewForMovie.bounds;
*   self.player.view.autoresizingMask =
*   UIViewAutoresizingFlexibleWidth |
*   UIViewAutoresizingFlexibleHeight;
*  
*   [self.viewForMovie addSubview:player.view];
*   [self.player play];
 }

Getting access to the MPMoviePlayerController’s video view is easy; we just access the player’s view property like any other property, and that’s what we’re doing in this code. After we have a reference to the view, we’re first setting two properties: the view’s frame and a couple of masks that control how the view can be resized. The frame, like the frame of any view, controls its onscreen size. Here, we’re getting the frame from the movieForView object and mirroring that. For the masks, we’re setting the view so that if necessary, it can be resized by width or height.

Now for the interesting part: we’re taking the player controller’s view and adding it as a subview to the viewForMovie view that we created earlier in Interface Builder. With that done, we send the player the play message to start the show. At this point, just build and run your project and you should see video playing in your UIView, just like the picture in the margin. Touching the view should expose some controls, including a fullscreen control, and rotating the device should give you reasonable resizing behavior. (The movie we're showing is copyright the Blender Foundation).

The Big Picture, or What Just Happened?

Let’s think about what just happened—it can get a bit confusing the first time through. While this may seem a bit complex, once you get past all the views and controllers involved, it is actually fairly simple.

What we’ve done is create a MPMoviePlayerController object that acts as the controller for displaying video content. We can use this controller to manage all the aspects of video playback, including stop, start, pause, and other actions. This controller also exposes a built-in property called view that we can obtain a reference to and then add to our own views in order to display video. And that’s exactly what we did. We first created an UIView in Interface Builder to act as a landing place for the video view, then, after creating the MPMoviePlayerController, we took its internal view and added it as a subview to our UIView.

The result? Video playback right in our iPad application.

Daniel H Steinberg wrote Cocoa Programming: A Quick Start guide for Developers, the Pragmatic Programmers’ best-selling book on developing Cocoa applications for Snow Leopard. A long-time Mac developer, Daniel also teaches courses on Mac OS X, iPhone, and iPad development for the Pragmatic Studios.

Eric T Freeman is a media company executive and co-author of two best-selling books: Head First Design Patterns and Head First HTML with CSS & XHTML. A computer scientist with a passion for media and software architectures, Eric has been an Apple programmer since the days of the Newton. Eric holds a Ph.D. from Yale University.

Send the authors your feedback or discuss the article in the magazine forum.