Return-Path: <env_1009244896006989@hermes.sun.com>
Received: from fort-point-station.mit.edu by po10.mit.edu (8.9.2/4.7) id LAA19068; Tue, 19 Feb 2002 11:56:25 -0500 (EST)
Received: from hermes.sun.com (hermes.sun.com [64.124.140.169])
	by fort-point-station.mit.edu (8.9.2/8.9.2) with SMTP id LAA27369
	for <alexp@mit.edu>; Tue, 19 Feb 2002 11:56:24 -0500 (EST)
Date: Tue, 19 Feb 2002 16:56:24 GMT+00:00
From: "JDC Tech Tips" <body_1009244896006989@hermes.sun.com>
To: alexp@mit.edu
Message-Id: <1009244896006989@hermes.sun.com>
Subject: JDC Tech Tips, February 19, 2002 (Java Media Framework, JSObject)
Precedence: junk
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
X-Mailer: Beyond Email 

 J  D  C    T  E  C  H    T  I  P  S


                      TIPS, TECHNIQUES, AND SAMPLE CODE



WELCOME to the Java Developer Connection(sm) (JDC) Tech Tips, 
February 19, 2002. This issue covers:

         * Playing Audio and Video With the Java(tm) Media 
           Framework 
         * Using the JSObject Class in Applets
         
These tips were developed using Java 2 SDK, Standard Edition, 
v 1.3 and Java Media Framework 2.1.1. 

This issue of the JDC Tech Tips is written by John Zukowski, 
president of JZ Ventures, Inc. (http://www.jzventures.com).

You can view this issue of the Tech Tips on the Web at
http://java.sun.com/jdc/JDCTechTips/2002/tt0219.html

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
PLAYING AUDIO AND VIDEO WITH THE JAVA MEDIA FRAMEWORK

You can use the Core Java 2 Platform libraries to display still 
images in GIF, JPEG, and PNG format. The libraries also provide
limited support for displaying animation through the GIF89A image 
format. You can also play WAV, AU, MIDI, and AIFF-formatted audio 
files. This support might be sufficient for your programs, but
if you need to work with other rich media formats, such as 
AVI files for video or MP3 files for audio, you need the Java 
Media Framework (JMF) API. 

The JMF API supports the playing, streaming, and capturing of 
audio and video. It provides a series of encoders and decoders to 
support different formats and offers a pluggable architecture for 
you to add support for additional formats.

The latest version of the Java Media Framework software 
(JMF 2.1.1 a) is available for download from 
http://java.sun.com/products/java-media/jmf/.
The JMF download comes in two flavors: a platform-specific 
version and a cross-platform version. Sun provides 
platform-specific versions for Solaris and Windows. (A Linux 
version is also available from Blackdown.)

The Sun platform-specific versions include audio support through 
native libraries for the Java Sound API, the cross-platform 
version does not. After downloading the installation, you need to 
configure your machine to use the JMF libraries. With the 
platform-specific library versions, you need to add the jmf.jar 
and sound.jar files to your class path, and the JMF lib directory 
to your path. For the cross-platform version, you need to add 
a reference to the jmf.jar file into your class path.

The Linux version comes in three flavors and supports both audio 
and video. For additional information and installation 
instructions see
http://www.blackdown.org/java-linux/jdk1.2-status/jmf-status.html 

Playing multimedia files through the JMF libraries is simple. The 
key classes are Manager and Player. The Manager has a series of 
createPlayer() methods that each return a Player. After you 
create a Player, you tell the Player to start playing. For basic 
audio playing, all you need to do is:

  Player player = Manager.createPlayer(resource);
  player.play();

The resource you pass into the createPlayer method can be one of 
three things: DataSource, MediaLocator, or URL. These represent 
different ways of specifying media: as a protocol handler 
(DataSource), through its content (MediaLocator), or by it 
location (URL). In most cases, working with the URL resources is 
simplest. For example, if you want to play a file that is on your 
local hard drive, you simply:

1. Get the URL for the file through the toURL method of the File
   class).

2. Pass the URL as the resource to createPlayer.

3. Play the file using the play method:

  URL url = file.toURL();
  Player player = Manager.createPlayer(url);
  player.play();

This process is not sufficient to play video. Calling play() for 
a video file is like watching your favorite video with the 
television set turned off. You might hear the audio but there's 
no picture. In order to get a picture you need to do a little 
extra work, such as register a ControllerListener.

The Player is a type of Controller, and controllers let you 
register a ControllerListener. The ControllerListener contains 
a single method 
public void controllerUpdate(ControllerEvent event). You use the 
method to find out when various events happen with the media, 
such as when the end of a video file is reached, when an audio
file has been loaded, or when the playing of media data has 
started and stopped. 

To respond to these events use the ControllerAdapter class.
ControllerAdapter offers more than thirty different methods to 
respond to specific types of controller events. Each of these
methods dispatches to a stub-method. Typically, you subclass the
ControllerAdapter to override the specific method or methods of 
interest with your own event-handling logic. If you don't use 
this approach, you need to check for the correct type of event 
using instanceof in the controllerUpdate method.

An event subtype that is particularly important is 
RealizeCompleteEvent. When this event happens, the 
ControllerAdapter delegates the handling to the realizeComplete 
method. Overriding this method permits you to get the visual 
component for the video player and the control panel
component for audio and video playing. The control panel is 
where you can control audio volume, and start or stop video. 
Here is how you can get the different components and add them to 
your display.

  Component vc = player.getVisualComponent();
  if (vc != null) {
    contentPane.add(vc, BorderLayout.CENTER);
  }
  Component cpc = player.getControlPanelComponent();
  if (cpc != null) {
    contentPane.add(cpc, BorderLayout.SOUTH);
  }

The following example puts together all the features discussed 
here. The program provides a button that brings up a JFileChooser 
to select what file you want to play. The program then acquires
a player for the file, and starts playing the file. This triggers 
the acquisition of the visual components being added to the 
screen. All the JMF-related code is in the load method of the 
program. Beyond that, the remainder of the code just manages the 
GUI.

You might wonder why the program stops the player before it 
starts another one. When you issue a Manager.createPlayer(url) 
call to create a new Player object, it is necessary to stop the 
prior one before starting the new one. If you don't stop the old 
player, you might hear an MP3 file playing while watching a video 
with its own sound track. If the video plays first, you need to 
remove the visual component for the video player, or else you see 
the "old" video clip, while listening to the new audio file.

  import javax.swing.*;
  import javax.media.*;
  import java.awt.*;
  import java.awt.event.*;
  import java.net.*;
  import java.io.*;
  
  public class PlayVideo extends JFrame {
  
    Player player;
    Component center;
    Component south;
  
    public PlayVideo() {
      setDefaultCloseOperation(EXIT_ON_CLOSE);
      JButton button = new JButton("Select File");
      ActionListener listener = 
          new ActionListener() {
        public void actionPerformed(
            ActionEvent event) {
          JFileChooser chooser = 
            new JFileChooser(".");
          int status = 
            chooser.showOpenDialog(PlayVideo.this);
          if (status == 
              JFileChooser.APPROVE_OPTION) {
            File file = chooser.getSelectedFile();
            try {
              load(file);
            } catch (Exception e) {
              System.err.println("Try again: " + e);
            }
          }
        }
      };
      button.addActionListener(listener);
      getContentPane().add(button, 
        BorderLayout.NORTH);
      pack();
      show();
    }
  
    public void load(final File file) 
        throws Exception {
      URL url = file.toURL();
      final Container contentPane = 
        getContentPane();
      if (player != null) {
        player.stop();
      }
      player = Manager.createPlayer(url);
      ControllerListener listener = 
          new ControllerAdapter() {
        public void realizeComplete(
            RealizeCompleteEvent event) {
          Component vc = 
            player.getVisualComponent();
          if (vc != null) {
            contentPane.add(vc, 
              BorderLayout.CENTER);
            center = vc;
          } else {
            if (center != null) {
              contentPane.remove(center);
              contentPane.validate();
            }
          }
          Component cpc = 
            player.getControlPanelComponent();
          if (cpc != null) {
            contentPane.add(cpc, 
              BorderLayout.SOUTH);
            south = cpc;
          } else {
            if (south != null) {
              contentPane.remove(south);
              contentPane.validate();
            }
          }
          pack();
          setTitle(file.getName());
        }
      };
      player.addControllerListener(listener);
      player.start();
    }
  
    public static void main(String args[]) {
      PlayVideo pv = new PlayVideo();
    }
  }

For more information about using JMF, see the Java Media 
Framework API Guide at 
http://java.sun.com/products/java-media/jmf/2.1.1/guide/JMFTOC.html

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
USING THE JSOBJECT CLASS IN APPLETS

Applets are Java technology programs that run in the browser. 
Under most circumstances, an applet does its processing within 
the realm of the Java Runtime Environment (JRE). There are times
however when it is necessary to jump out of the applet's secure
runtime environment (the "sandbox") and communicate with the 
browser. The communication is done through the LiveConnect 
facility, and permits applets to work with JavaScript. The bulk 
of this communication is performed through the 
netscape.javascript.JSObject class.

Originally provided as part of the Netscape browser environment,
Microsoft eventually added this package to the runtime that 
ships with Internet Explorer. In addition, the package is now 
a standard part of the Java Runtime Environment installed with 
the Java Plug-in. That means that applets can use the package and 
expect to find the package when they execute. It isn't necessary 
to include the classes with a deliverable program.

In order to develop applets that take advantage of this package, 
you need to add the necessary classes to your class path. The
Java runtime environment already puts these classes in your 
runtime class path, by default. However the development 
environment doesn't. So you need to make available to your 
development environment the jaws.jar file (Windows) or
javaplugin.jar file (Solaris) that ships with the Java Runtime.

Assuming that you use the Java 2 Standard Edition (J2SE) 
version 1.3 Software Development Kit (SDK), you can place the 
jaws.jar file (Windows) in the jre\lib\ext directory or
javaplugin.jar file (Solaris) in the jre/lib/ext directory under 
the installation directory for your SDK. Once copied, the 
appropriate classes (and others) will be available to your 
program.

As previously mentioned, the key class for applet-to-JavaScript
communications is the JSObject class. This class provides, among
other things, the means to call JavaScript methods and evaluate 
raw JavaScript syntax. To demonstrate these capabilities, let's 
create an applet that prompts for raw HTML in its TextArea. Then 
let's open up a new browser window to display the HTML. Because
the raw HTML is in the TextArea and not in a file, you can't just 
call the showDocument() method to open up a new URL.

The first thing you need to do to communicate with JavaScript is 
get a JSObject instance. The class has no constructor. Instead, 
you call the getWindow method of the class, passing in 
a parameter of the applet instance:

JSObject topWindow = JSObject.getWindow(this);

Calling methods on the JSObject object is done using the call 
method. This method works by passing in the text name of the 
method to invoke, and an Object array of the arguments. 

public Object call(String name, Object args[])

To pass in arguments, you create the array, and then fill it, 
based upon how many arguments are necessary:

Object args[] = new args[x]
args[0] = ...;
args[1] = ...;
...
args[x] = ...;

For instance, to open a window you need to call the open method 
of the window object. Because getWindow returns the window 
associated with the applet, you already have the window object. 
The open method accepts three arguments:

* The URL of what to open
* The name of the window
* Any attributes as a comma-separated list

The attributes describe how the window will look. Some of the 
more standard ones are:

* width (number)
* height (number)
* location (boolean)
* menubar (boolean)
* scrollbars (boolean)
* status (boolean)
* toolbar (boolean)

The boolean values can be yes, no, 1, or 0.

For instance, if you want a 300x300 window with no location, 
menubar, status bar, or toolbar, the attribute string would look 
like this:

"width=300,height=300,location=0,menubar=0,status=0,toolbar=0"

Using that attribute string, you can open an unnamed window (with 
no content) with a three element array where only the third
element is set:

  Object args[] = {"","","width=..."};

Then, pass those arguments and the method name on to the call 
method of the window received from the prior getWindow call.

  topWindow.call("open", args);

To actually fill the window with the contents from the TextArea, 
you must call the write method on the named "document" member 
within the window.

Getting the document member involves calling the getMember method
and passing it the name of the member you want, in this case, 
document:

  JSObject document = (
            JSObject)popupWindow.getMember("document");

You then need to call the write method of document to change the 
content of the window. Here, you simply construct another 
argument array, this time with only one element for the text:


String htmlText = ...;

  args = new Object[] {htmlText};

Then, call the write method:

  document.call("write", args);

That's essentially all there is to communicating with the 
JSObject object. Another thing you might want to do with JSObject 
is call the eval method. Given a string, the eval method treats 
the string as a JavaScript expression and evaluates it.

Here is an applet that puts together all the pieces that were 
covered in this tip:

  import java.applet.*;
  import java.awt.*;
  import java.awt.event.*;
  import netscape.javascript.*;

  public class JSPopup extends Applet {
    public void init() {
      final TextArea ta = new TextArea();
      Button button = new Button("Launch");
      ActionListener listener = 
          new ActionListener() {
        public void actionPerformed(ActionEvent e) {
          String htmlText = ta.getText();
          JSObject topWindow = 
            JSObject.getWindow(JSPopup.this);
          Object args[] = new Object[3];
          args[2] = "width=300,height=300," +
          "location=0,menubar=0,status=0,toolbar=0";
          JSObject popupWindow = 
            (JSObject)topWindow.call("open", args);
          JSObject document = (JSObject)
            popupWindow.getMember("document");
          args = new Object[] {htmlText};
          document.call("write", args);
        }
      };
      button.addActionListener(listener);
      setLayout(new BorderLayout());
      add(ta, BorderLayout.CENTER);
      add(button, BorderLayout.SOUTH);
    }
  }

When using applet-to-JavaScript communications, you must set the 
MAYSCRIPT parameter. This tells the security environment to allow
the two systems to communicate.

<applet code=JSPopup width=300 height=300>
<PARAM NAME="MAYSCRIPT" VALUE="TRUE">
</applet>

Compile the applet and then run it in your browser. Then enter 
some HMTL content in the text area:

<H1>Hello, World</H1>

Then click the Launch button in the applet. You should see a new 
window displayed. If you don't see a new window, try using a 
different browser (a number of bugs have been reported 
regarding Java-JavaScript communications with 1.3.1 Plugin and 
Netscape).

You could also use this technique to display the response from 
applet-to-servlet communications where the applet has to manually 
send a POST request to the servlet.

Even without Java Plugin installed, you can still use the 
netscape.javascript.JSObject class with the native virtual 
machine in Internet Explorer 4.x - 6.x and Netscape Communicator 
4.7x. The JavaScript communications support in a native virtual 
machine differs from that provided with the Java Plug-in. The 
basics described in this tip are the same. However, the native 
virtual machines rely on an older version of the package. You can 
find documentation for the older package at 
http://home.netscape.com/eng/mozilla/3.0/handbook/plugins/doc/
Package-netscape.javascript.html

.  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .

IMPORTANT: Please read our Terms of Use, Privacy, and Licensing 
policies:
http://www.sun.com/share/text/termsofuse.html
http://www.sun.com/privacy/ 
http://developer.java.sun.com/berkeley_license.html

* FEEDBACK
  Comments? Send your feedback on the JDC Tech Tips to: 
  jdc-webmaster@sun.com

* SUBSCRIBE/UNSUBSCRIBE
  - To subscribe, go to the subscriptions page,
    (http://developer.java.sun.com/subscription/), choose
    the newsletters you want to subscribe to and click "Update".
  - To unsubscribe, go to the subscriptions page,
    (http://developer.java.sun.com/subscription/), uncheck the
    appropriate checkbox, and click "Update".
  - To use our one-click unsubscribe facility, see the link at 
    the end of this email:
    
- ARCHIVES
You'll find the JDC Tech Tips archives at:

http://java.sun.com/jdc/TechTips/index.html


- COPYRIGHT
Copyright 2002 Sun Microsystems, Inc. All rights reserved.
901 San Antonio Road, Palo Alto, California 94303 USA.

This document is protected by copyright. For more information, see:

http://java.sun.com/jdc/copyright.html


JDC Tech Tips 
February 19, 2002

Sun, Sun Microsystems, Java, and Java Developer Connection, are 
trademarks or registered trademarks of Sun Microsystems, Inc. in 
the United States and other countries.


To use our one-click unsubscribe facility, select the following URL:
http://bulkmail.sun.com/unsubscribe?1009244896006989
