It's not that we think O'Reilly readers skip the developer docs or ignore
the demos that come with the SDK, but we just want to be sure we're good before
we hit the hard stuff. After all, there's matrix math coming up when
we get to sprite animation ...

I will be using this article in the future for reference purposes, in the
sense of "If this is your first time writing a QTJ app, go back to this
article and make sure you've got everything set up correctly." Between
horrid CLASSPATH issues and the obtuse situation with QTJ and Java 1.4.1 on Mac OS X, it'll be nice to not have to reiterate three paragraphs of
gotchas every time.

A Little Background ...

Apple's QuickTime for
Java is a Java wrapper around much of the native QuickTime media API, which
itself has been available and under ongoing development since 1991. It is
available for the classic Mac OS, Mac OS X, and Windows. Note the obvious
omission: it is not available for Linux or any other OS at
this time; nor is there an all-Java version.

QuickTime is sometimes thought of as just a media format and player, a rival
to Windows Media and Real Player, with support for a wide
variety of media formats, including some that most people aren't aware of
(such as Flash 5 and Photoshop). But that thinking overlooks the fact that it
was designed as a media creation API, with tools to capture and edit
media, apply effects, and to export to different formats. QuickTime also includes a
legacy imaging API, sprites, and support for interactivity within a movie. QuickTime used
to include a 3D API, QuickDraw 3D, but it was dropped in Mac OS X in favor of OpenGL. We won't discuss it
again.

QuickTime had been around for years before the QTJ project started, and was
designed for use with straight C — not necessarily C++ or Objective-C.
While QTJ re-envisions QuickTime from a more object-oriented perspective, QTJ
code still seems different than what you might be used to working with in
JavaSoft's APIs. For example, while most classes in core Java and the standard
extensions define constants in the classes where they are used (e.g.,
Label.LEFT, Integer.MAX_VALUE), QTJ defines massive
lists of constants in StdQTConstants,
StdQTConstants4, etc., which hints at their origin as members of
big C header files like Movies.h.

By the way, Apple's sample code has a tendency to declare that it
implements these no-method interfaces, which is an easy-to-write
but hard-to-follow way of inheriting the constants. In my sample code, I will
always explicitly reference the constant by class so you can find it again
later.

When Not to Use QuickTime for Java

Let me start with the ultimate in simplicity — not using QTJ at all.
Every once in a while, someone will post the to the quicktime-java
list that they need to learn QTJ because they want to put a movie in an applet
in a web page.

That is overkill. Since it requires the user to have Java, QuickTime, and
QuickTime for Java all installed, the size of the potential audience is smaller
than it would be without so many dependencies.

If all you want to do is put a QuickTime movie in a web page, just use a
pair of simple HTML tags. Most browsers will pick up the <EMBED> tag, but since Internet Explorer is special, it needs an <OBJECT> tag. Here's a simple example of a suitable tag:

Some of these values are boilerplate and never change, namely the
<object>'s classid and codebase,
and the <embed>'s pluginspage. Beyond that,
the variables that you populate simply need to get repeated as both
<param> children of the <object> tag and
attributes of the <embed> tag. The only required values for
the simplest case are:

src: The URL of the movie

height and width: Dimensions of the movie. If
you intend to show the controller (the bar with the volume control, play/pause
button, and the "scrubber"), add 16 pixels to the height.

I've added an entry, autoplay, as another attribute, mostly just
to keep things interesting — it doesn't have a default value, since
general autoplay behavior is determined by the user's QuickTime preferences.
This and many more attributes are described in Apple's document "Embedding QuickTime
for Web Delivery."

You could also drop the controller, instead controlling the movie through
your own HTML buttons, links, or other page elements. You can do this with the
QuickTime plug-in's JavaScript
support. In this case, just add the attribute enablejavascript =
true to the <embed> tag (it's not necessary for the
<object> tag), give it a name attribute and
parameter, and then refer to the movie by that name when you call methods such
as Play() and Stop(), as in this example. More sophisticated methods are available for getting and setting movie properties like the playback rate
and volume, examining the track structure of the movie, and getting limited
access to sprite and QuickTime VR properties.

The downside of the JavaScript support is that it is only as good as the
LiveConnect — or, in QuickTime 6, XPCOM — support in your browser.
For QuickTime 6, that means that Mozilla and Internet Explorer work fine on
Windows, but the situation is a disaster on the Mac, where only Mozilla
supports JavaScript control of the QuickTime plug-in. IE is known not to work,
and while Apple says that Mozilla-based browsers should be OK, Camino and
OmniWeb don't work with my example, nor does Safari beta 2 (v.72).

One option to get a lot of mileage out of authoring (in lieu of coding) is
to use the "Synchronized Multimedia Integration Language", or SMIL
(pronounced "smile"). This XML markup, a WC3 standard, allows you to present audio, video, text, and other elements, from multiple sources, in one display, using the markup to arrange the elements temporally and spatially, indicating
what goes where and when.

In the <head> tag, we define a number of spatial
"regions". Our content will refer to these to indicate where it will
be placed on the screen. You can have any number of regions, with several used at
a time.

References to media go in the <body> section, grouped
according to whether different items are "parallel" or in
"sequence." Items in a <par> tag are shown or
played at the same time, while those in a <seq> tag are
shown or played one after another, either for their natural duration (if
appropriate) or for the time specified in a "dur" attribute.

Our example pairs an audio clip (a 15-second soundtrack from FreePlay Music, whose royalty-free audio clips are available to .Mac users via the iDisk Software folder), with a sequence of elements. The first four
members of the sequence are graphics: the ONJava logo, an "and" graphic, the MacDevCenter logo, and a "presents" graphic. Note that Apple's SMIL docs include a way to include text from a file or a data:
URL, but I used graphics so I could control the font and color.

The last member of the sequence is another <par> tag,
this time combining a poster frame, keagy-closeup.jpeg, with two
image links to the movie. Notice that the link elements refer to two regions
whose z-index is 2, while the main
region has a z-index of 1. This causes the link graphics to be
drawn on top of the poster image.

Among the many possible uses of SMIL, this illustrates a way to create
"alternate movies" (movies that redirect to other QuickTime movies,
perhaps to offer different sizes or bitrates). This is easier than the technique
offered here. (If you don't scare easily, check out the low-level
details of how this kind of real "alternate movie" works, along
with an audacious QuickTime
for Java implementation.)