Movies and Menus01/25/2002
A number of readers have been asking for a column describing how to use Cocoa and QuickTime together. I hope today's article appeases those requests. (Now, if I only knew a little more about networking ...)
So today I'll cover how to incorporate QuickTime media into Cocoa applications. I also have a few things to say about menus, which are not too closely related to QuickTime, but a movie player makes as good an app as any for using menus. Specifically, I'll show you how you can give your application contextual menus, and even a dock menu.
Before I get too far into the column, let me warn you that I'm not an expert with the QuickTime API. In fact, I'm not even a novice. This column is the first time I've really even come close to looking at the QuickTime API documentation. But that's not the point anyway; we're here to see how we can put movies into our application. So let's see how.
NSMovie and NSMovieView
The two classes that we will use to work with QuickTime movies are
NSMovie is a wrapper class that provides an object-oriented interface to QuickTime data. Specifically,
NSMovie provides a simple interface for loading movie data into memory, and subsequently accessing it.
For those of you interested in hardcore QuickTime programming, let me say that you can obtain a pointer to the QuickTime data using the
-movie. This will then allow you to use the QuickTime framework to access and manipulate the data. For our purposes, we will focus our efforts on using
NSMovie is more of a vehicle for loading data than manipulating it.
NSMovieView (or movie view) is a subclass of
NSView; it is a view for displaying the data of
NSMovie objects. By default, a movie view presents users with the standard set of controls for playing and editing a QuickTime movie. This can be disabled in favor of, or supplemented with, a custom interface.
NSMovieView provides methods that give us complete control over the playback of the movie. Later in the column, we will do just this with a simple menu-driven interface.
For now, let's get our feet wet by building the interface, which is as simple as dragging a movie view container onto the window, and constructing a simple controller object with an outlet to the container.
Building the Interface
Let's start by creating a new project called SimpleMoviePlayer by selecting File > New Project. Open the file
MainMenu.nib by double-clicking in Project Builder, and Interface Builder will open. The interface we intend to create is very straightforward. Within the Cocoa-GraphicsViews palette, you'll see the QuickTime logo; this is an
NSMovieView, which is similar to the
NSView container we had previously employed. Drag this onto your window and the container will appear. Resize it to fill the window.
Be aware of one thing regarding the NSMovieView: any movie played in the view will be resized to fit, so it's a good idea to resize the view to an appropriate size such as 320x240, or 480x256. If you want to easily resize a movie you'll need QuickTime Pro ($29.99) to make adjustments to your content. To resize simply go to File --> Export. Make sure you have "Movie to QuickTime Movie" selected in the dropdown menu, then click the Options button. In Options, click the Size button to set your new dimensions. For the best looking results, keep your proportions consistent as you resize.
As I said before, I'm not familiar with the QuickTime programming API, but I imagine that a function exists to return the dimensions of a movie. If we could do this, we could then resize the view to fit the movie when we load it. If anyone knows how to do this, feel free to post it.
At this point you should take a few moments to familiarize yourself with the available options in the Attributes of the
NSMovieView container. With the movie view highlighted, type Command-1 to bring up the attributes. Today, we won't make any changes here, but feel free to muck around with them at will.
Now we need create a Controller class for the application. In the Classes tab of the nib window, highlight NSObject and press return to subclass it. As always, name the subclass Controller. Now press Command-1 to bring up the attributes in the Info panel. To the Controller, we want to add one outlet named
movieView, and one action method named
openMovie:. Next, instantiate Controller by selecting Classes > Instantiate.
movieView will be connected to the
NSMovieView container in the window. The action
openMovie: will, of course, be used to open a movie and load it into the view. Make sure the MainMenu.nib - Main Menu window is open. We will connect the Open... menu item to the
openMovie: action of Controller. To do this, Control-drag from the Open... menu item onto the Controller and make the connection.
With that, we are now ready to create the files to be added to the project, and return to PB to do our coding. Choose Controller from the Classes tab, and then choose the menu item Classes > Create Files For Controller. Now let's get to come coding.
Loading the Movie
This next section has to do with the code that we'll write to load a movie into the view. This requires two fundamental steps. The first step is to create a new instance of
NSMovie and initialize it to load our movie data from disk into memory. We create the new instance using
+alloc, and we'll then initialize it using the
|Let's talk about this latest cocoa tutorial.|
The second step will tell the
NSMovieView in our window to display the
NSMovie instance we just created. We do this by sending a
-setMovie: message to the movie view with our
NSMovie object as the argument.
Now we've got a missing link here -- we're kind of working backwards up to the final code for
openMovie:. We have to supply
initWithURL:byReference: a URL to the movie file, rather than a regular string file path.
This is a bit different for us. We've always used simple file paths to open files on our disks, never really URLs, but in this case we need to use URLs. But that's not a problem. Cocoa handles URLs with the class
NSURL. With this class you can make URLs from standard strings. Rather than hardcode a URL into the application, we will allow the user to pick the file to open. This is made possible by the class