December 94 - Somewhere in QuickTime: Supporting Text Tracks in Your Application
Somewhere in QuickTime: Supporting Text Tracks
in Your Application
Nick Thompson
Text media tracks were introduced with QuickTime version 1.5 and have been further
improved in QuickTime 2.0 with the addition of calls for more powerful searching and
a new facility called burnt text. The big news is that text tracks are now supported in
QuickTime for Windows version 2.0, which makes text tracks a cross-platform
solution. If you're developing content-based products that need to be cross-platform,
you'll want to take a look at text tracks.
Text tracks give you the ability to embed text in a QuickTime movie, which is
particularly useful if you're aiming your product at international markets or at
people with hearing impairments (you can subtitle your movie) or if you want to
enable your users to perform searches (by including the script of a play or movie in a
text track, for instance, you can make it easy for users to find a particular scene by
searching for a key piece of dialog). The possibilities for adding value to your
QuickTime application and content with text tracks are limited only by your
imagination.
This column shows you how to add text track support to your QuickTime application,
including support for searching and editing. The sample program QTTextSample on this
issue's CD demonstrates what's involved. This small application plays a movie
controller-based movie in a window and offers users the ability to search for a
particular sequence of characters, or edit the text, in the text track.
Text tracks are handled by the text media handler, which is documented in the "Movie
Toolbox" chapter of Inside Macintosh: QuickTime. The text media handler's
functionality includes the following:
• Searching for text, using FindNextText. With QuickTime 2.0, a new
routine for text searching, MovieSearchText, can be used. This call is also
available with QuickTime 2.0 for Windows.
• Adding plain or styled text, using AddTextSample or AddTESample. Both
of these calls allow you to define additional text properties, such as scrolling
and highlighting.
Searching is something that all applications that support text tracks will want to offer
the user, while editing text is likely to be something that only a few specialized
applications will want to provide. Editing of text can be accomplished with Movie
Toolbox routines, as discussed later in this column.
FIRST THINGS FIRST
Your QuickTime application needs to do a few basic things at the outset, as
QTTextSample demonstrates. These include checking for the QuickTime version
number, growing your heap as large as possible, and checking return codes.
QuickTime version number. A Macintosh application that supports text tracks
requires QuickTime version 1.5 or later; a Windows application that supports text
tracks requires QuickTime 2.0 for Windows. On Macintosh platforms you can use the
Gestalt selector gestaltQuickTime to check that the version number returned in the
high-order word is greater than or equal to the required version (0x0150 for
QuickTime 1.5; 0x0200 for QuickTime 2.0).
Our sample program bails out if the system isn't running QuickTime version 1.5 or
later. If your application uses calls provided by later releases of QuickTime but you
also want it to run on earlier versions, you should check for the version number and
selectively enable your application's functionality accordingly.
Heap size. As discussed in the Somewhere in QuickTime column indevelop Issue 13
("Top 10 QuickTime Tips" by John Wang), you need to ensure that you grow your heap
as large as possible in your initialization code by calling the MaxApplZone routine.
QuickTime needs to use a lot of handle-based data structures, so you also need to ensure
that there are enough master pointers allocated in the base of your heap. To do that,
you should call MoreMasters a number of times (you can tell how many times by
examining your heap while the application is running). If you don't do this, your heap
may become fragmented, which in turn may cause certain QuickTime routines to fail
due to lack of memory. This is a general Macintosh programming issue that you should
be aware of for all applications.
Return codes. Finally, always check those return codes, and handle errors as
required. Most QuickTime routines return a status code of type OSErr; if this isn't
equal to noErr, you have problems. QuickTime is always trying to tell you something
-- listen and your life will be more complete!
THE USER INTERFACE
The user interface for the sample application is pretty basic. Figure 1 shows the
application window. As you can see, the text for the movie is repeated below the movie
so that it can be edited. Buttons offer the user the options of finding specific text or
updating the text with editing changes. (The Update Text button is dimmed unless the
text in the text box has been modified.)
With text track selected
With movie selected
Figure 1. The application window for QTTextSample
Because the user can potentially edit two items -- the movie's text track or the movie
itself -- the application needs to keep track of what the user selected last (either text
or the movie) and highlight it in some way. As shown in Figure 1, when the text track
is selected in our sample application, the text below the movie has a black box around
it; when the movie is selected, the movie frame has a black box around it. When the
window is inactive (for example, when you switch applications), the box surrounding
the active item is rendered in gray.
TRICKS FOR EASY ACCESS
In the sample code, the movie controller is stored in a record referenced by a handle
stored in the window's refCon, along with a few other bits and pieces related to the
movie and the text for a window. This gives us easy access to both the movie controller
and its associated movie:
aDocHdl = (DocHandle)GetWRefCon(theMovieWindow);
aController = (**aDocHdl).myController;
aMovie = MCGetMovie(aController);
When we need to locate the first track of a particular type (in our case a text track) in
a movie, we can use the following handy utility routine:
Track GetFirstTrackOfType (Movie aMovie,
OSType trackType)
Track theTrack = nil;
OSType mediaType;
short trackCount, index;
trackCount = GetMovieTrackCount(aMovie);
for (index=1; index <= trackCount; index++) {
Track t = GetMovieIndTrack(aMovie, index);
GetMediaHandlerDescription(GetTrackMedia(t),
&mediaType, nil, nil);
if (mediaType == trackType) {
theTrack = t;