QuickTime Developer Series


Sample Chapter

Integrating QuickTime with Java

As we've seen in Chapter 1, QuickTime for Java represents a library of classes that are designed to bring the power and functionality of QuickTime to Java. The core library of these classes provides you with the ability to access many features and capabilities in the QuickTime API. The second set of classes--an Application Framework--lets you integrate those capabilities into your Java programs.

This chapter discusses how that integration works. The topics discussed include the following:

  • a brief introduction to some Java terminology
  • grouping QuickTime for Java classes into a set of packages based on common functionality and usage
  • classes in the Application Framework built on top of QuickTime for Java native binding classes
  • the QTSimpleApplet and PlayMovie programs explained method by method

In this and the following chapters, many code listings are given that use the various QuickTime components and structures. A brief introduction to QuickTime is given and its major components and structures discussed in Chapter 2, "QuickTime Basics." More information is available in the various books and reference material for QuickTime that is presented on the CD-ROM at the back of this book and at the QuickTime website http://www.apple.com/quicktime , where the complete QuickTime reference documentation and SDK are available.

Some Java Terminology

If you're a C or C++ programmer, you'll need to understand some of the key terms in the Java programming language before proceeding with the QuickTime for Java API.

In Java, you can think of an object as a collection of data values, or fields. In addition, there are methods that operate on that data. The data type of an object is called a class; and an object is referred to as an instance of its class. In object-oriented programming, the class defines the type of each field in the object. The class also provides the methods that operate on data that is contained in an instance of the class. You create an object using the new keyword. This invokes a constructor method of the class to initialize the new object. You access the fields and methods of an object by using the dot (.) operator.

In Java, methods that operate on the object itself are known as instance methods. These are different from the class methods. Class methods are declared static ; and they operate on the class itself rather than on an individual instance of the class. The fields of a class may also be declared static , which makes them class fields instead of instance fields. Each object that you instantiate in Java has its own copy of each instance field, but there is only one copy of a class field, which is shared by all instances of the class.

Fields and methods of a class may have different visibility levels, namely, public , protected , package , and private . These different levels allow fields and methods to be used in different ways.

Every class has a superclass. And from that superclass it inherits fields and methods. When a class inherits from another class, it is called a subclass of that class. This inheritance relationship forms what is known as a class hierarchy. The java.lang.Object class is the root class of all Java classes; Object is the ultimate superclass of all other classes in Java.

An interface is a Java construct that defines methods, like a class. However, it does not provide implementations for those methods. A class can implement an interface by defining an appropriate implementation for each of the methods in the interface. An interface expresses the methods an object can perform--what a class can do--while making no assumptions about how the object implements these methods.

When compiled, Java classes generate a class file that is a byte- coded representation of the class. When a Java program is run, these byte codes are interpreted and often compiled (with a Just-in-Time Compiler) into the native or machine code of the runtime environment and then executed. This is the part of the work done by the Java Virtual Machine (VM). These byte codes are platform-independent and can be executed on any platform that has a Java VM.

A method in a Java class can be declared to be a native method. A native method has no Java code; it assumes that the method is actually defined in a native library, typically in C. Native methods are used for a number of reasons: performance, access to native services provided by the operating system, and so on. In fact, many of the classes in the java.* packages contain native methods in order for the Java classes to intergrate with an existing operating system.

Part of the distribution of QuickTime for Java is a framework of classes. A package name (package and import) is a qualification that precedes the name of a class, i.e., it defines a name-space. The java.* packages are the standard set available on any distribution. QuickTime for Java uses quicktime.* to delineate the QuickTime for Java name-space.

You may want to refer to Appendix A for an explanation of the nomenclature that is used in the QuickTime for Java API. Appendix A also discusses some of the guidelines used in naming methods and classes.

A View of the QuickTime to Java Integration

The following diagram illustrates a top-level view of the QuickTime to Java integration.

The QuickTime and Java integration

Binding QuickTime Functions to Java Methods

Java classes are created from structures and data types found in the standard QuickTime C language header files. These data types provide the basic class structure of the QuickTime for Java API. For example, the Movie data type in Movies.h becomes the Movie class. In general, the C function calls list the main data structure they operate on as the first parameter of the function. These calls become methods in this class. In line with Java conventions, all class names are capitalized, while method names are not.

Functions to Methods

The methods of a class are created from C functions. There is generally a one-to-one relationship between a native function call and a Java method. The Java method's name is derived by the following procedure:

The QuickTime native function

SetMovieGWorld

logically translates (or is bound by) the Java method

setGWorld on the Movie class.

The QuickTime native function

MCSetControllerPort

logically translates (or is bound by) the Java method

setPort on the MovieController class.

A complete list of the QuickTime functions that QuickTime for Java binds is provided on the CD-ROM at the back of this book. The javadoc-generated documentation in HTML, also on the CD-ROM, lists for each method the related QuickTime function call in bold. For example:

QuickTime::EnterMovies()

The supplied HTML documentation for these binding calls provides only brief descriptions. You need to refer to the QuickTime documentation both for specific details of a particular API, as well as for general discussions on the usage of particular services. QuickTime documentation is available on the QuickTime website.

Garbage Collection

As Java has a built-in garbage collection mechanism, the QuickTime for Java classes perform their own memory management. There are no explicit dispose calls in the QuickTime for Java API. These calls are called by the objects themselves when they perform garbage collection. The quicktime.util.QTUtils.reclaimMemory() method requests that the garbage collector run and can be used to help ensure disposed of memory that is no longer referenced.

The QuickTime for Java API contains no direct access to pointers or other features that are common in a C-based API. The Java method calls provide very little overhead to the native call; they do parameter marshalling and check the result of the native call for any error conditions. If an error is returned by the native call, then an exception is thrown.

Threads

Although Java is a multithreaded environment, the method calls that map a QuickTime function to a Java method do not provide any implicit synchronization support. If you share any QuickTime object between threads, you are responsible for dealing with any synchronization issues that may arise. The Java language provides easy services to let you do this by means of the following syntax as well as synchronized method calls:

synchronize (aJavaObject) { /*synchronized block of code*/ }

The QuickTime for Java Package Structure

The QuickTime for Java classes are grouped into a set of packages. The grouping is based on common functionality and usage and on their organization in the standard QuickTime header files. The packages provide both an object model for the QuickTime API and a logical translation or binding of the native function calls into Java method calls. A number of packages also have subpackages that group together smaller sets of functionality.

The major packages generally have a constants interface that presents all of the constants that relate to this general grouping and an exception class that all errors that derive from a call in this package group will throw. The packages, with descriptions of their principal classes and interfaces, are shown in the following table .

QuickTime for Java packages

Package

Principal classes
and interfaces

Description

quicktime

QTSession, QTException

The QTSession class has calls that set up and intialize the QuickTime engine, such as initialize , gestalt , and enterMovies .

quicktime.io

OpenFile, QTFile, OpenMovieFile, QTIOException

Contains calls that deal with file I/O. These calls are derived from the Movies.h file.

quicktime.qd

QDGraphics, PixMap, Region, QDRect, QDColor, QDConstants, QDException

Contains classes that represent the QuickDraw data structures that are required for the rest of the QuickTime API. These calls are derived from the QuickDraw.h and QDOffscreen.h files. The QuickTime API expects data structures that belong to QuickDraw, such as graphics ports, GWorlds, rectangles, and points.

quicktime.qd3d

CameraData, Q3Point, Q3Vector

Contains classes that represent the QuickDraw 3D data structures that are required for the rest of the QuickTime API, predominantly the tweener and 3D media services.

quicktime.sound

SndChannel, Sound, SPBDevice, SoundConstants, SoundException

Contains classes that represent the Sound Manager API. These calls are derived from the Sound.h file. While some basic sound recording services are provided, for more demanding sound input and output the sequence grabber components and movie playback services should be used.

quicktime.std

StdQTConstants, StdQTException

The original QuickTime interfaces on the Mac OS are contained in a collection of eight header files that describe the standard QuickTime API. As such, nearly all of the functions defined in these files are to be found in classes in the quicktime.std group of packages.

quicktime.std.
anim

Sprite, SpriteWorld

Classes that provide support for animation. QuickTime can be used as a real-time rendering system for animation, distinct from a data format--that is, the movie. Thus, you can create a graphics space ( SpriteWorld ) within which characters ( Sprite objects) can be manipulated.

quicktime.std.
clocks

Clock, TimeBase, QTCallback and subclasses

Contains classes that provide timing services, including support for the creation of hierarchical dependencies between time bases, the usage of callbacks for user scheduling of events or notification, and the capability of instantiating the system clocks that provide the timing services.

quicktime.std.
com

Component, Component-
Description

QuickTime is a component-based architecture, with much of its funtionality being provided through the creation and implementation of a particular component's API. This package contains classes that provide basic support for this component architecture; a full implementation is forthcoming.

quicktime.std.
image

CodecComponent, QTImage, CSequence, Matrix

Contains classes that present the Image Compression Manager. These classes provide control for the compression and decompression of both single images and sequences of images. It also contains the Matrix class, which (like the Region class in the qd package) is used generally throughout QuickTime to alter and control the rendering of 2D images.

quicktime.std.
movies

AtomContainer, Movie, MovieController, Track

Contains the principal data structures of QuickTime, including classes that represent QuickTime atom containers, movies, movie controllers, and tracks--all essential for creating and manipulating QuickTime movies. A movie containing one or more tracks is the primary way that data is organized and managed in QuickTime. A Movie object can be created from a file or from memory and can be saved to a file. The MovieController class provides the standard way that QuickTime data (movies) are presented and controlled. AtomContainer objects are the standard data structures used to store and retrieve data in QuickTime.

quicktime.std.
movies.media

DataRef, Media and subclasses, MediaHandler
and subclasses , Sample
Description
and subclasses

A Track object is a media neutral structure, but it contains a single Media type that defines the kind of data that a Track is representing. The Media , MediaHandler and SampleDescription subclasses describe the various media types that QuickTime can present. Media classes control references to data that comprise the raw media data.

quicktime.std.
music

AtomicInstrument,
NoteChannel, NoteAllocator

Contains classes that deal with the general music architecture provided by QuickTime. This architecture can be used to capture and generate music (MIDI) events in real time, customize and create instruments, and eventually provide your own algorithmic synthesis engines.

quicktime.std.
qtcomponets

MovieExporter, MovieImporter, TimeCoder

Contains classes that interface with some of the components that are provided to supply different services. The import and export components are supported, as are tween and timecode media components.

quicktime.std.sg

SequenceGrabber, SGVideoChannel, SGSoundChannel

Contains classes that implement the sequence grabber component for capturing video and audio media data.

quicktime.util

QTHandle, QTByteObject, QTPointer, UtilException

Contains classes that represent utility functionality required by the general QuickTime API. The most commonly used feature of this package is set of classes for memory management from Memory.h . These classes typically form the base class for actual QuickTime objects.

quicktime.vr

QTVRConstants, QTVRInstance, QTVRException

Contains classes that represent the QuickTime Virtual Reality API. The package contains all the QuickTime VR interface constants, the QTVRInstance class and some QTVR callbacks for presentation of QTVR content.



QuickTime Headers and Java Classes

As we've seen, Java classes are created from structures and data types found in the standard QuickTime C language header files. These provide the basic class structure of the QuickTime for Java API. The original QuickTime interfaces on the Mac OS are contained in a collection of eight header files that describe the standard QuickTime API. As such, nearly all of the functions defined in these files are to be found in classes in the quicktime.std group of packages.

The standard QuickTime C header files with their corresponding packages in the QuickTime for Java API are shown in the table below .

C header files and corresponding QuickTime for Java packages

QuickTime C header files

Description

Components.h

Calls from this file are in the quicktime.std.comp package.

ImageCompression.h and
ImageCodec.h

Calls from this file are in the quicktime.std.image package.

MediaHandlers.h

Not required in QuickTime for Java.

Movies.h

This file has been separated into a number of packages to present a finer degree of definition and functional grouping.
Sprite animation calls are in the quicktime.std.anim package.
Callback and time-base calls are in the quicktime.std.clocks package.
File I/O calls are in the quicktime.io package.
All media-related calls are in the quicktime.std.movies.media package.
Movies, movie controllers, tracks, and atom containers are in the quicktime.std.movies package.

MoviesFormat.h

Not required in QuickTime for Java.

QuickTimeComponents.h

This file has been separated into a number of packages to present a finer degree of definition and functional grouping. The clocks component is found in the quicktime.std.clocks package. Sequence grabber components calls are found in the quicktime.std.sg package. The remaining components are found in the quicktime.std.qtcomponents package.

QuickTimeMusic.h

All calls from this file are in the quicktime.std.music package.



The Application Framework

The classes in the QuickTime for Java Application Framework are built entirely on top of QuickTime for Java native binding classes.

The Application Framework classes are designed to simplify the usage of the QuickTime for Java API and to provide a close integration with Java's display and event distribution system. They offer a set of services that are commonly used by QuickTime programs. In addition, they provide useful abstractions and capabilities that make the use of these services simpler and easier for the developer.

The Framework itself is also designed with reusability and extensibility of classes in mind. It uses Java interfaces to express some of the functionality that can be shared or is common among different classes. You can also implement your own versions of these interfaces, or extend existing implementations, to more specifically meet a particular requirement, and in so doing, use these custom classes with other classes of the Framework itself. The following table describes the various Framework packages and their principal classes.

QuickTime for Java Application Framework packages

Package

Description

quicktime.app

Provides a set of "factory" methods for creating classes that you can use to present media that QuickTime can import. In addition, it provides some utility methods for finding directories and files in the local file system.

quicktime.app.action

Contains a large number of useful controller classes for mouse drags and for handling mouse events. It also contains action classes that can be used to apply actions to target objects.

quicktime.app.anim

Contains classes that present all of the functionality of the Sprite and SpriteWorld .

quicktime.app.audio

Contains a number of interfaces and classes that deal specifically with the audio capabilities of QuickTime.

quicktime.app.display

Contains a number of classes that are important for using the QuickTime for Java API. QTCanvas and QTDrawable negotiate with java.awt classes to allow the presentation of QuickTime content within a Java window or display space.

quicktime.app.image

Handles the presentation and manipulation of images. Included are utility classes for setting transparent colors in images, applying visual effects, creating objects for handling sequences of images, and QTDrawable objects that read image data from a file or load the data into memory.

quicktime.app.players

QTPlayer and MoviePlayer define a set of useful methods that enables you to present QuickTime movies, using QTCanvas objects and the QTDrawable interface.

quicktime.app.sg

Contains a single class, SGDrawer .

quicktime.app.spaces

Interfaces in this package provide a uniform means of dealing with a collection of objects in QuickTime for Java.

quicktime.app.time

Provides a set of useful classes to handle timing services used to schedule regular tasks that need to be performed on an ongoing basis.



The QTSimpleApplet

The sample code on the accompanying CD-ROM includes QTSimpleApplet , a QuickTime for Java applet you can create that presents any of the media file formats that QuickTime supports. QuickTime includes support for a vast array of common file formats: QuickTime movies (including QuickTime VR), pictures, sounds, MIDI, and QuickDraw 3D.

The applet tag for this applet is

<applet code="QTSimpleApplet.class" width=200 height=100>
<param name="file" value="media/crossfad.gif">
</applet>

The test.html file on the CD-ROM contains the complete HTML listing, including the use of a JavaScript script to generate the appropriate tag. The QTSimpleApplet code takes any of the media file types supported by QuickTime as a parameter in the HTML applet tag and creates the appropriate object for that media type:

param name=file value="MyMediaFile.xxx"

The QTCanvas , QTDrawable , and QTFactory classes, which are part of the QTSimpleApplet code, are discussed in greater detail in Chapter 4, "QTCanvas, QTDrawable, and QTFactory."

As with all Java applets, we begin in the QTSimpleApplet code by declaring a list of Java packages and QuickTime for Java packages that contain the required classes you need to import:

import java.applet.Applet;
import java.awt.*;
import quicktime.QTSession;
import quicktime.io.QTFile;

import quicktime.app.QTFactory;
import quicktime.app.display.QTCanvas;
import quicktime.app.display.Drawable;
import quicktime.QTException;

To get the resources for the simple applet and set up the environment, including the creation of the QTCanvas object, you use the init() method, as shown in the snippet below. QTCanvas is the object responsible for handling the integration from the java.awt side between Java and QuickTime. The QTCanvas also has parameters that let you control the resizing of the client that it presents. In this case, we tell the canvas to center the client within the space given by the applet's layout manager. This ensures that the client is only as big as its initial size (or smaller if you make the canvas smaller).

The QTSession.open() call performs a gestalt check to make sure that QuickTime is present and is initialized. Note that this is a required call before any QuickTime for Java classes can be used:

public void init () {
try {
QTSession.open()

To set up a QTCanvas object that displays its content at its original size or smaller and is centered in the space given to the QTCanvas when the applet is laid out, we do the following:

setLayout (new BorderLayout());
myQTCanvas = new QTCanvas (QTCanvas.kInitialSize, 0.5F,
0.5F);
add (myQTCanvas, "Center");

QTFile file = new QTFile (getCodeBase().getFile() +
getParameter("file"));
myQTContent = QTFactory.makeDrawable (file);
} catch (Exception e) {
e.printStackTrace();
...
}
}

The QTFactory.makeDrawable() method is used to create an appropriate QuickTime object for the media that is specified in the <PARAM> tag.

If a QTException is thrown in the init() method, an appropriate action should be taken by the applet, depending on the error reported.

In the start() method shown in the next code snippet, you set the client of the QTCanvas . This QTCanvas.client is the QuickTime object (i.e., an object that implements the QTDrawable interface) that draws to the area of the screen that the QTCanvas occupies. This is the QuickTime side of the integration between Java and QuickTime:

public void start () {
try { myQTCanvas.setClient (myQTContent, true);
} catch (Exception e) {
e.printStackTrace();
}
}

You use the stop() method to remove the client from the QTCanvas . It will be reset in the start() method if the applet is restarted. destroy() is used to close the QTSession . This protocol enables the applet to be reloaded, suspended, and resumed--for example, if the user is leaving and returning to the page with the applet. The init() / destroy() and start() / stop() methods are reciprocal in their activities:

public void stop () {
myQTCanvas.removeClient();
}

public void destroy () {
QTSession.close();
}

You need to call QTSession.close() if you have previously called QTSession.open() in order to shut down QuickTime properly.

The QTTestApplet on the accompanying CD-ROM at the back of this book lists a version of the simple applet that allows for the contingencies of QuickTime or QuickTime for Java not being present when an applet is launched. The init() method may throw exceptions because the required file was not found or the applet does not have permission from Java's security manager to read that file. Alternatively, the required version of QuickTime may not be installed. The applet should deal with these issues appropriately.

Comparing QuickTime C and Java Code

Much of the sample code available for QuickTime is presented in the C programming language. Comparing Getting a movie from a file using C code and Playing a movie (also in C code) with the Java version shown in PlayMovie.java can aid in understanding how to translate C to Java code.

Getting a Movie from a File

Before your application can work with a movie, you must load the movie from its file. You must open the movie file and create a new movie from the movie stored in the file. You can then work with the movie. You use the OpenMovieFile function to open a movie file and the NewMovieFromFile function to load a movie from a movie file. The code in Getting a movie from a file using C code shows how you can use these functions.

Getting a movie from a file using C code

Movie GetMovie (void)
{
OSErr err;
SFTypeList typeList = {MovieFileType,0,0,0};
StandardFileReply reply;
Movie aMovie = nil;
short movieResFile;

StandardGetFilePreview (nil, 1, typeList, &reply);
if (reply.sfGood)
{
err = OpenMovieFile (&reply.sfFile, &movieResFile,
fsRdPerm);

if (err == noErr)
{
short movieResID = 0; /* want first movie */
Str255 movieName;
Boolean wasChanged;
err = NewMovieFromFile (&aMovie, movieResFile,
&movieResID,
movieName,
newMovieActive, /* flags */
&wasChanged);
CloseMovieFile (movieResFile);
}
}
return aMovie;
}

The Movie Toolbox uses Alias Manager and File Manager functions to manage a movie's references to its data. A movie file does not necessarily contain the movie's data. The movie's data may reside in other files, which are referred to by the movie file. When your application instructs the Movie Toolbox to play a movie, the Toolbox attempts to collect the movie's data. If the movie has become separated from its data, the Movie Toolbox uses the Alias Manager to locate the data files. During this search, the Movie Toolbox automatically displays a dialog box. The user can cancel the search by clicking the Stop button.

The code in Playing a movie shows the steps your application must follow in order to play a movie. This program retrieves a movie, sizes the window properly, plays the movie forward, and exits. This program uses the GetMovie function shown in Getting a movie from a file using C code to retrieve a movie from a movie file.

Playing a movie

#include <Types.h>
#include <Traps.h>
#include <Menus.h>
#include <Fonts.h>
#include <Packages.h>
#include <GestaltEqu.h>
#include "Movies.h"
#include "ImageCompression.h"

/* #include "QuickTimeComponents.h" */

#define doTheRightThing 5000

void main (void)
{
WindowPtr aWindow;
Rect windowRect;
Rect movieBox;
Movie aMovie;
Boolean done = false;
OSErr err;
EventRecord theEvent;
WindowPtr whichWindow;
short part;

InitGraf (&qd.thePort);
InitFonts ();
InitWindows ();
InitMenus ();
TEInit ();
InitDialogs (nil);
err = EnterMovies ();
if (err) return;

SetRect (&windowRect, 100, 100, 200, 200);
aWindow = NewCWindow (nil, &windowRect, "\pMovie",
false, noGrowDocProc, (WindowPtr)-1,
true, 0);

SetPort (aWindow);
aMovie = GetMovie ();
if (aMovie == nil) return;

GetMovieBox (aMovie, &movieBox);
OffsetRect (&movieBox, -movieBox.left, -movieBox.top);
SetMovieBox (aMovie, &movieBox);

SizeWindow (aWindow, movieBox.right, movieBox.bottom, true);
ShowWindow (aWindow);

SetMovieGWorld (aMovie, (CGrafPtr)aWindow, nil);

StartMovie (aMovie);
while ( !IsMovieDone(aMovie) && !done )
{
if (WaitNextEvent (everyEvent, &theEvent, 0, nil))
{
switch ( theEvent.what )
{
case updateEvt:
whichWindow = (WindowPtr)theEvent.message;
if (whichWindow == aWindow)
{
BeginUpdate (whichWindow);
UpdateMovie(aMovie);
SetPort (whichWindow);
EraseRect (&whichWindow->portRect);
EndUpdate (whichWindow);
}
break;

case mouseDown:
part = FindWindow (theEvent.where,
&whichWindow);
if (whichWindow == aWindow)
{
switch (part)
{
case inGoAway:
done = TrackGoAway (whichWindow,
theEvent.where);
break;
case inDrag:
DragWindow (whichWindow,
theEvent.where,
&qd.screenBits.bounds);
break;
}
}
break;
}
}
MoviesTask (aMovie, DoTheRightThing);
}
DisposeMovie (aMovie);
DisposeWindow (aWindow);
}

Playing a QuickTime Movie

PlayMovie.java shows how to display any QuickTime content within a java.awt display space using the QTCanvas . It also demonstrates the use of the different resize options of the QTCanvas (with the alignment set to center it in the display space). You use the movie controller to select and then play a QuickTime movie, which can be a local file or a URL specified by the user.

You call QTSession.open() to perform a gestalt check to ensure that QuickTime is present and is initialized. This is a required call before any QuickTime Java classes can be used.

The window is the size of the movie and resizing the window will resize the movie. The QTCanvas is set to allow any size and is the central component in a java.awt.BorderLayout of its parent Frame .

You use the following methods to lay out and resize the Frame to the size of the Movie :

pm.pack();
pm.show();
pm.toFront();

You now prompt the user to select a movie file:

QTFile qtf = QTFile.standardGetFilePreview(QTFile.kStandardQTFileTypes);

You open the selected file and make a movie from it, using these calls:

OpenMovieFile movieFile = OpenMovieFile.asRead(qtf);
Movie m = Movie.fromFile (movieFile);

You construct a movie controller from the resultant movie, enabling the keys so the user can interact with the movie using the keyboard:

MovieController mc = new MovieController (m);
mc.setKeysEnabled (true);

You create a QTCanvas so that the MovieController has somewhere to draw and add it to the Frame :

QTCanvas myQTCanvas = new QTCanvas();
add (myQTCanvas);

You construct the QTDrawable object to present a movie controller:

QTPlayer myQTPlayer = new QTPlayer (mc);

Now you set it as the drawing client of the QTCanvas for a QTPlayer . This also registers interests for both mouse and key events that originate in the QTCanvas :

myQTCanvas.setClient (myQTPlayer, true);

You add a WindowListener to this frame that will close down the QTSession . Finally, you dispose of the Frame that closes down the window and you exit:

addWindowListener(new WindowAdapter () {
public void windowClosing (WindowEvent e) {
QTSession.close();
dispose();
}

public void windowClosed (WindowEvent e) {
System.exit(0);
}
});

When the user closes the window, the program quits, first calling QTSession.close to terminate QuickTime. You need to call QTSession.close() if you have previously called QTSession.open() in order to shut down QuickTime properly. QTSession.close() is called before the canvas that the QuickTime object is attached to is disposed of. This enables QuickTime to clean up its graphics objects, which it attaches to the native implementation of the QTCanvas .

PlayMovie.java

import java.awt.*;
import java.awt.event.*;

import quicktime.*;
import quicktime.io.*;
import quicktime.std.movies.*;
import quicktime.app.display.QTCanvas;
import quicktime.app.players.QTPlayer;

public class PlayMovie extends Frame {

public static void main (String args[]) {
try {
QTSession.open ();
PlayMovie pm = new PlayMovie("QT in Java");
pm.pack();
pm.show();
pm.toFront();
} catch (QTException e) {
// handle errors
. . .
}
}

PlayMovie (String title) throws QTException {
super (title);

QTFile qtf = QTFile.standardGetFilePreview(QTFile.kStandardQTFileTypes);

OpenMovieFile movieFile = OpenMovieFile.asRead(qtf);
Movie m = Movie.fromFile (movieFile);

MovieController mc = new MovieController (m);
mc.setKeysEnabled (true);

QTCanvas myQTCanvas = new QTCanvas();
add (myQTCanvas);

QTPlayer myQTPlayer = new QTPlayer (mc);

myQTCanvas.setClient (myQTPlayer, true);

addWindowListener(new WindowAdapter () {
public void windowClosing (WindowEvent e) {
QTSession.close();
dispose();
}

public void windowClosed (WindowEvent e) {
System.exit(0);
}
});
}
}

Summary Comparision

We've seen two bodies of code illustrated in several examples, one in C and the other in Java. In summary, we could note the following points:

  • Both pieces of code can open and play a vast number of media files.
  • The C code is specific to the Macintosh; the Windows version (not shown) is different--though only slightly. Of course, as an application in C is developed around QuickTime, more and more platform-specific code needs to be written, whereas with Java, a framework is provided that is a cross-platform API as well as a cross-platform execution model.
  • The Java code benefits from the Java class framework with which a developer may already be familiar.
  • Java runs anywhere, unchanged, so long as QuickTime is available. As other client operating systems gain QuickTime support, the QuickTime for Java code will run there, too.
  • The Java code is arguably simpler.

 


Home | Updates | Corrections | FAQ | Table of Contents |