Integrating QuickTime with Cocoa

This is the first in a series of articles about integrating QuickTime
technology into your Cocoa applications. My intent with this series
is to provide the introductory steps for those of you who are new to
QuickTime, to cover many of the common tasks and issues that may crop
up during your development cycle, and to share my experience so that, hopefully,
you can avoid some of the mistakes I've made along the way.

I'll start out by providing an overview of QuickTime, then some insight
into the interfaces between Cocoa and QuickTime, and finish up with
an example of a "simple" QuickTime Movie Player that you can
include in your own applications.

What is QuickTime?

In the early 1990s, Apple introduced QuickTime, a collection of application
programmer interfaces (APIs) and components that support the creation,
manipulation, and playback of multimedia and interactive content. Using
the QuickTime API, programmers can work with media types such as video,
images, and audio, as well as vector-based graphics and animation, 3D
modeling data, panoramic objects, MIDI-formatted music, and user-defined
media types. QuickTime components provide access to variety of services,
such as image compression/decompression, video digitizing, and pre-defined
effects that can be performed on one or more media types.

The movie is used as a metaphor to describe any time-based sequence of
data that can be manipulated by QuickTime. The data can be a sequence
of images (like a cinematic movie), or audio samples, or stock quotes,
or any type of data that varies over time. A typical movie might contain
several streams of data, called tracks. For example, a .mov file might
contain a movie with two streams, a video track and a sound track.

The QuickTime API is quite extensive and beyond the scope of this article.
So I would suggest that before you begin a project of your own that
you spend some time with the QuickTime documentation
available at the Apple developer web site.

QuickTime Comes to Cocoa

During the 1990s, QuickTime had helped Apple become successfully positioned
as a leader in multimedia and interactive technology. So, when Apple
bought NeXT in the late 1990s, the challenge facing Apple was how to
integrate one of its homegrown key technologies with Cocoa, the new
development environment acquired from NeXT. QuickTime did not have an
object-oriented interface and was based on QuickDraw, Apple's pre-Mac-OS-X imaging architecture. Cocoa, on the other hand, was defined by
the objects in Foundation and AppKit. Cocoa's image architecture was
also based on Quartz, the PDF-based graphical system that Apple had
chosen as its go-forward technology.

The solution was to introduce two new objects into Cocoa's AppKit. The
NSMovie object was provided to encapsulate the QuickTime
movie metaphor, and NSMovieView provided insulation from
the differences in the underlying image architectures.

All of QuickTime in One Object?

Let's take a look at the NSMovie object. This object fits
my notion of a shallow encapsulation. The NSMovie class
contains only a few methods, which provide you with access to the QuickTime
Movie data type, but does not allow you to directly modify
the movie's data. In other words, using NSMovie, you can
get a pointer to the movie for display purposes, but you can't use NSMovie
itself to change a movie's playback attributes or contents.

The NSMovie class contains methods that allow you to do
three basic things:

Initialize a new NSMovie object.

Filter the file types used for initialization.

Return basic info about the QuickTime Movie
pointer being encapsulated.

First, NSMovie objects can be initialized from a URL, a
pasteboard, or an existing QuickTime Movie pointer. NSMovie
can be initialized with any type of data that QuickTime will accept
using the methods -initWithURL:byReference, -initWithPasteboard,
or -initWithMovie. This includes video, audio, and still
images. Also, you may need to use a URL for initialization from HTTP
and RSTP resources.

The following example shows how to initialize an instance of NSMovie
using a sample movie contained in an application's bundle:

Second, NSMovie provides methods to help you filter file
types and pasteboards that can be used to initialize an object instance.
Using -canInitWithPasteboard and -movieUnfilteredPasteboardTypes,
you can test the suitability for initialization using a particular pasteboard
or retrieve a list of pasteboard types that will be accepted. Additionally,
you may also find it useful to use -movieUnfilteredFileTypes
to restrict the choices a user has when selecting files.

The following is an example of how you might use NSMovie
to filter the file types that will be selectable from an NSOpenPanel.

Finally, NSMovie can be used to return information about
the QuickTime movie that it has encapsulated. The method -QTMovie
returns the QuickTime Movie pointer that is the source
for the NSMovie object. This is the key ingredient for
extending the value of NSMovie when working with QuickTime.
With a Movie pointer in hand, you can use functions from
the QuickTime API to access, manipulate, and change any QuickTime attributes
that are unavailable from NSMovie.

The following example illustrates how to access several QuickTime movie
attributes that are not available from NSMovie:

On the Screen, Please!

Okay, so you have an NSMovie object ... now what? Most of
the time, the answer to that question will be that you need to play
it. That's where NSMovieView comes in.

Figure 1. An NSMovieView

Figure 1 illustrates a typical use of NSMovieView. In this
case, the view is displayed with a movie controller, which allows the
user to play the movie, set the volume, reposition the play head, and
make selections.

Before you get started working with NSMovieView, I recommend
that you get thoroughly familiar with the features and behavior of Apple's
QuickTime Player. Much of the functionality of NSMovieView
is demonstrated directly in the features of the QuickTime Player.