- •Contents
- •Preface
- •Introduction to Computers, the Internet and the Web
- •1.3 Computer Organization
- •Languages
- •1.9 Java Class Libraries
- •1.12 The Internet and the World Wide Web
- •1.14 General Notes about Java and This Book
- •Sections
- •Introduction to Java Applications
- •2.4 Displaying Text in a Dialog Box
- •2.5 Another Java Application: Adding Integers
- •2.8 Decision Making: Equality and Relational Operators
- •Introduction to Java Applets
- •3.2 Sample Applets from the Java 2 Software Development Kit
- •3.3 A Simple Java Applet: Drawing a String
- •3.4 Two More Simple Applets: Drawing Strings and Lines
- •3.6 Viewing Applets in a Web Browser
- •3.7 Java Applet Internet and World Wide Web Resources
- •Repetition)
- •Class Attributes
- •5.8 Labeled break and continue Statements
- •5.9 Logical Operators
- •Methods
- •6.2 Program Modules in Java
- •6.7 Java API Packages
- •6.13 Example Using Recursion: The Fibonacci Series
- •6.16 Methods of Class JApplet
- •Class Operations
- •Arrays
- •7.6 Passing Arrays to Methods
- •7.8 Searching Arrays: Linear Search and Binary Search
- •Collaboration Among Objects
- •8.2 Implementing a Time Abstract Data Type with a Class
- •8.3 Class Scope
- •8.4 Controlling Access to Members
- •8.5 Creating Packages
- •8.7 Using Overloaded Constructors
- •8.9 Software Reusability
- •8.10 Final Instance Variables
- •Classes
- •8.16 Data Abstraction and Encapsulation
- •9.2 Superclasses and Subclasses
- •9.5 Constructors and Finalizers in Subclasses
- •Conversion
- •9.11 Type Fields and switch Statements
- •9.14 Abstract Superclasses and Concrete Classes
- •9.17 New Classes and Dynamic Binding
- •9.18 Case Study: Inheriting Interface and Implementation
- •9.19 Case Study: Creating and Using Interfaces
- •9.21 Notes on Inner Class Definitions
- •Strings and Characters
- •10.2 Fundamentals of Characters and Strings
- •10.21 Card Shuffling and Dealing Simulation
- •Handling
- •Graphics and Java2D
- •11.2 Graphics Contexts and Graphics Objects
- •11.5 Drawing Lines, Rectangles and Ovals
- •11.9 Java2D Shapes
- •12.12 Adapter Classes
- •Cases
- •13.3 Creating a Customized Subclass of JPanel
- •Applications
- •Controller
- •Exception Handling
- •14.6 Throwing an Exception
- •14.7 Catching an Exception
- •Multithreading
- •15.3 Thread States: Life Cycle of a Thread
- •15.4 Thread Priorities and Thread Scheduling
- •15.5 Thread Synchronization
- •15.9 Daemon Threads
- •Multithreading
- •Design Patterns
- •Files and Streams
- •16.2 Data Hierarchy
- •16.3 Files and Streams
- •Networking
- •17.2 Manipulating URIs
- •17.3 Reading a File on a Web Server
- •17.4 Establishing a Simple Server Using Stream Sockets
- •17.5 Establishing a Simple Client Using Stream Sockets
- •17.9 Security and the Network
- •18.2 Loading, Displaying and Scaling Images
- •18.3 Animating a Series of Images
- •18.5 Image Maps
- •18.6 Loading and Playing Audio Clips
- •18.7 Internet and World Wide Web Resources
- •Data Structures
- •19.4 Linked Lists
- •20.8 Bit Manipulation and the Bitwise Operators
- •Collections
- •21.8 Maps
- •21.9 Synchronization Wrappers
- •21.10 Unmodifiable Wrappers
- •22.2 Playing Media
- •22.3 Formatting and Saving Captured Media
- •22.5 Java Sound
- •22.8 Internet and World Wide Web Resources
- •Hexadecimal Numbers
1238 |
Java Media Framework and Java Sound (on CD) |
Chapter 22 |
In addition to the sample media clips provided with this chapter’s examples on the CD, many Web sites offer an abundant supply of free-for-download audio and video clips. You can download media clips from these sites (and many others on the Internet) and use them to test the examples in this chapter. We present a list of sites here to get you started. Free Audio Clips (www.freeaudioclips.com) is an excellent site for various types of audio files. The 13 Even site (www.13-even.com/media.html) provides audio and video clips in many formats for your personal use. If you are looking for MIDI audio files for use in Section 22.7, check out the free MIDI clips at www.freestuffgalore.commidi.asp. Funny Video Clips (www.video-clips.co.uk) offers entertaining material. Microsoft’s downloads site (msdn.microsoft.com/downloads) contains a multimedia section providing audio clips and other media.
Currently, JMF is available as an extension package separate from the Java 2 Software Development Kit. The CD that accompanies this book contains JMF 2.1.1. The most recent JMF implementation can be downloaded from the official JMF Web site:
java.sun.com/products/java-media/jmf
The JMF Web site provides versions of the JMF that take advantage of the performance features of the platform on which the JMF is running. For example, the JMF Windows Performance Pack provides extensive media and device support for Java programs running on Microsoft Windows platforms (Windows 95/98/NT 4.0/2000). JMF’s official Web site also provides continually updated support, information and resources for JMF programmers.
Portability Tip 22.1
Writing programs using JMF’s Windows Performance Pack reduces the portability of those programs to other operating systems.
The rest of this chapter discusses the Java Sound API and its extensive sound-pro- cessing capabilities. Internally, the JMF uses Java Sound for its audio functions. In Sections 22.5 through 22.7, we will demonstrate sampled audio playback and MIDI functionalities using Java Sound, a standard extension of the Java 2 Software Development Kit.
22.2 Playing Media
The JMF is commonly used to playback media clips in Java applications. Many applications such as financial managers, encyclopedias and games use multimedia to illustrate application features, present educational content and entertain users.
The JMF offers several mechanisms for playing media, the simplest of which is via objects that implement interface Player. Interface Player (package javax.media) extends Controller, which is a handler for JMF-supported media.
The following steps are needed to play a media clip:
1.Specify the media source.
2.Create a Player for the media.
3.Obtain the output media and Player controls.
4.Display the media and controls.
Class SimplePlayer (Fig. 22.1) is a simple Java media player program that demonstrates several common features of popular media players. The SimplePlayer demo
Chapter 22 |
Java Media Framework and Java Sound (on CD) |
1239 |
can play most JMF-supported media files with the possible exception of the latest versions of the formats. This application permits users to access files on the local computer that contain supported media types by clicking the Open File button. Clicking the Open Location button and specifying a media URL allows the user to access media from a media source, such as a capture device, a Web server, or a streaming source. A capture device (discussed in Section 22.3) reads media from audio and video devices such as microphones, CD players and cameras. A Real-Time Transport Protocol (RTP) stream is a stream of bytes sent over a network from a streaming server. An application buffers and plays the streaming media on the client computer.
1// Fig. 22.1: SimplePlayer.java
2// Opens and plays a media file from
3 // local computer, public URL, or an RTP session
4
5 // Java core packages
6import java.awt.*;
7 import java.awt.event.*;
8 import java.io.*;
9 import java.net.*;
10
11// Java extension packages
12import javax.swing.*;
13import javax.media.*;
14
15 public class SimplePlayer extends JFrame {
16
17// Java media player
18private Player player;
20// visual content component
21private Component visualMedia;
23// controls component for media
24private Component mediaControl;
26// main container
27private Container container;
29// media file and media locations
30private File mediaFile;
31private URL fileURL;
32
33// constructor for SimplePlayer
34public SimplePlayer()
35{
36super( "Simple Java Media Player" );
38 container = getContentPane();
39
40// panel containing buttons
41JPanel buttonPanel = new JPanel();
Fig. 22.1 Playing media with interface Player (part 1 of 8).
1240 |
Java Media Framework and Java Sound (on CD) |
Chapter 22 |
42 container.add( buttonPanel, BorderLayout.NORTH );
43
44// opening file from directory button
45JButton openFile = new JButton( "Open File" );
46buttonPanel.add( openFile );
47
48// register an ActionListener for openFile events
49openFile.addActionListener(
50 |
|
51 |
// anonymous inner class to handle openFile events |
52 |
new ActionListener() { |
53 |
|
54 |
// open and create player for file |
55 |
public void actionPerformed( ActionEvent event ) |
56 |
{ |
57 |
mediaFile = getFile(); |
58 |
|
59 |
if ( mediaFile != null ) { |
60 |
|
61 |
// obtain URL from file |
62 |
try { |
63 |
fileURL = mediaFile.toURL(); |
64 |
} |
65 |
|
66 |
// file path unresolvable |
67 |
catch ( MalformedURLException badURL ) { |
68 |
badURL.printStackTrace(); |
69 |
showErrorMessage( "Bad URL" ); |
70 |
} |
71 |
|
72 |
makePlayer( fileURL.toString() ); |
73 |
|
74 |
} |
75 |
|
76 |
} // end actionPerformed |
77 |
|
78 |
} // end ActionListener |
79 |
|
80 |
); // end call to method addActionListener |
81 |
|
82// URL opening button
83JButton openURL = new JButton( "Open Locator" );
84buttonPanel.add( openURL );
85
86// register an ActionListener for openURL events
87openURL.addActionListener(
88 |
|
89 |
// anonymous inner class to handle openURL events |
90 |
new ActionListener() { |
91 |
|
92 |
// open and create player for media locator |
93 |
public void actionPerformed( ActionEvent event ) |
94 |
{ |
Fig. 22.1 Playing media with interface Player (part 2 of 8).
Chapter 22 |
Java Media Framework and Java Sound (on CD) |
1241 |
|
|
|
|
|
95 |
|
String addressName = getMediaLocation(); |
|
96 |
|
|
|
97 |
|
if ( addressName != null ) |
|
98 |
|
makePlayer( addressName ); |
|
99 |
|
} |
|
100 |
|
|
|
101 |
} |
// end ActionListener |
|
102 |
|
|
|
103 |
); // end call to method addActionListener |
|
|
104 |
|
|
|
105// turn on lightweight rendering on players to enable
106// better compatibility with lightweight GUI components
107Manager.setHint( Manager.LIGHTWEIGHT_RENDERER,
108 Boolean.TRUE );
109
110 } // end SimplePlayer constructor
111
112// utility method for pop-up error messages
113public void showErrorMessage( String error )
114{
115JOptionPane.showMessageDialog( this, error, "Error",
116JOptionPane.ERROR_MESSAGE );
117 |
} |
118 |
|
119// get file from computer
120public File getFile()
121{
122JFileChooser fileChooser = new JFileChooser();
124 |
fileChooser.setFileSelectionMode( |
125 |
JFileChooser.FILES_ONLY ); |
126 |
|
127 |
int result = fileChooser.showOpenDialog( this ); |
128 |
|
129 |
if ( result == JFileChooser.CANCEL_OPTION ) |
130 |
return null; |
131 |
|
132 |
else |
133return fileChooser.getSelectedFile();
134}
135
136// get media location from user input
137public String getMediaLocation()
138{
139String input = JOptionPane.showInputDialog(
140this, "Enter URL" );
142// if user presses OK with no input
143if ( input != null && input.length() == 0 )
144 |
return null; |
145 |
|
146return input;
147}
Fig. 22.1 Playing media with interface Player (part 3 of 8).
1242 |
Java Media Framework and Java Sound (on CD) |
Chapter 22 |
148
149// create player using media's location
150public void makePlayer( String mediaLocation )
151{
152// reset player and window if previous player exists
153if ( player != null )
154 |
removePlayerComponents(); |
155 |
|
156// location of media source
157MediaLocator mediaLocator =
158 new MediaLocator( mediaLocation );
159
160 if ( mediaLocator == null ) {
161 showErrorMessage( "Error opening file" );
162return;
163}
164
165// create a player from MediaLocator
166try {
167 |
player = Manager.createPlayer( |
mediaLocator ); |
168 |
|
|
169 |
// register ControllerListener |
to handle Player events |
170 |
player.addControllerListener( |
|
171 |
new PlayerEventHandler() ); |
|
172 |
|
|
173 |
// call realize to enable rendering of player's media |
174player.realize();
175}
176
177// no player exists or format is unsupported
178catch ( NoPlayerException noPlayerException ) {
179noPlayerException.printStackTrace();
180}
181
182// file input error
183catch ( IOException ioException ) {
184ioException.printStackTrace();
185}
186
187 } // end makePlayer method
188
189// return player to system resources and
190// reset media and controls
191public void removePlayerComponents()
192{
193// remove previous video component if there is one
194if ( visualMedia != null )
195container.remove( visualMedia );
196
197// remove previous media control if there is one
198if ( mediaControl != null )
199container.remove( mediaControl );
200
Fig. 22.1 Playing media with interface Player (part 4 of 8).
Chapter 22 |
Java Media Framework and Java Sound (on CD) |
1243 |
201// stop player and return allocated resources
202player.close();
203}
204
205// obtain visual media and player controls
206public void getMediaComponents()
207{
208// get visual component from player
209visualMedia = player.getVisualComponent();
211// add visual component if present
212if ( visualMedia != null )
213container.add( visualMedia, BorderLayout.CENTER );
215// get player control GUI
216mediaControl = player.getControlPanelComponent();
218// add controls component if present
219if ( mediaControl != null )
220 container.add( mediaControl, BorderLayout.SOUTH );
221
222 } // end method getMediaComponents
223
224// handler for player's ControllerEvents
225private class PlayerEventHandler extends ControllerAdapter {
227// prefetch media feed once player is realized
228public void realizeComplete(
229RealizeCompleteEvent realizeDoneEvent )
230{
231player.prefetch();
232}
233
234// player can start showing media after prefetching
235public void prefetchComplete(
236PrefetchCompleteEvent prefetchDoneEvent )
237{
238 |
getMediaComponents(); |
239 |
|
240 |
// ensure valid layout of frame |
241 |
validate(); |
242 |
|
243 |
// start playing media |
244 |
player.start(); |
245 |
|
246 |
} // end prefetchComplete method |
247 |
|
248// if end of media, reset to beginning, stop play
249public void endOfMedia( EndOfMediaEvent mediaEndEvent )
250{
251 player.setMediaTime( new Time( 0 ) );
252player.stop();
253}
Fig. 22.1 Playing media with interface Player (part 5 of 8).
1244 |
Java Media Framework and Java Sound (on CD) |
Chapter 22 |
254
255 } // end PlayerEventHandler inner class
256
257// execute application
258public static void main( String args[] )
259{
260SimplePlayer testPlayer = new SimplePlayer();
262testPlayer.setSize( 300, 300 );
263testPlayer.setLocation( 300, 300 );
264testPlayer.setDefaultCloseOperation( EXIT_ON_CLOSE );
265testPlayer.setVisible( true );
266}
267
268 } // end class SimplePlayer
Fig. 22.1 Playing media with interface Player (part 6 of 8).
Chapter 22 |
Java Media Framework and Java Sound (on CD) |
1245 |
|
|
|
|
|
|
Fig. 22.1 Playing media with interface Player (part 7 of 8).
1246 |
Java Media Framework and Java Sound (on CD) |
Chapter 22 |
|
|
|
|
|
|
Fig. 22.1 Playing media with interface Player (part 8 of 8).
A media clip must be processed before it is played. To process a media clip the program must access a media source, create a Controller for that source and output the media. Prior to output, users may perform optional formatting such as changing an AVI video to a QuickTime video. Although JMF hides low-level media processing (e.g. checking for file compatibility) from the programmer, both programmers and users can configure how a Player presents media. Section 22.3 and Section 22.4 reveal that capturing and streaming media follow the same guidelines. Section 22.8 lists several Web sites that have JMF-supported media contents.
Figure 22.1 introduces some key objects for playing media. The JMF extension package javax.media—imported in line 13—contains interface Player and other classes and interfaces needed for events. Line 18 declares a Player object to play media clips. Lines 30–31 declare the location of these clips as File and URL references.
Lines 21 and 24 declare Component objects for the video display and for holding the controls. Component mediaControl enables users to play, pause and stop the media clip. Component visualMedia displays the video portion of a media clip (if the media clip is a video). The JMF provides lightweight video renderers that are compatible with lightweight Swing components (See Chapter 13). Lines 107–108 in SimplePlayer’s constructor specify that the Player should draw its GUI components and video portion (if there
Chapter 22 |
Java Media Framework and Java Sound (on CD) |
1247 |
is one) using lightweight renderers so that the media player will look like other GUIs with Swing components. By default, Player’s video components are heavyweight components, which may not display correctly when mixed with lightweight Swing GUI components.
Before playing the media, SimplePlayer displays an initial GUI consisting of two buttons, Open File and Open Locator, that enable users to specify the media location. The event handlers for these two buttons (lines 52–78 and lines 90–101) perform similar functions. Each button prompts users for a media resource such as an audio or video clip, then creates a Player for the specified media. When the user clicks Open File, line 57 calls method getFile (lines 120–134) to prompt users to select a media file from the local computer. Line 63 calls the File method toURL to obtain a URL representation of the selected file’s name and location. Line 72 calls SimplePlayer method makePlayer (lines 150–187) to create a Player for the user-selected media. When users click Open Locator, line 95 invokes method getMediaLocation (lines 137–147), prompting users to input a String giving the media location. Line 98 calls SimplePlayer method makePlayer to create a Player for the media at the specified location.
Method makePlayer (lines 150–187) makes the necessary preparations to create a Player of media clips. The String argument indicates the media’s location. Lines 153– 154 invoke SimplePlayer method removePlayerComponents (lines 191–203) to remove the previous Player’s visual component and GUI controls from the frame before creating a new Player. Line 202 invokes Player method close to stop all player activity and to release system resources held by the previous Player.
Method makePlayer requires a pointer to the source from which the media is retrieved, which is accomplished by instantiating a new MediaLocator for the value given by the String argument (lines 157–158). A MediaLocator specifies the location of a media source, much like a URL typically specifies the location of a Web page. A MediaLocator can access media from capture devices and RTP sessions as well as from file locations. The MediaLocator constructor requires the media’s location as a String, so all URLs must be converted to Strings as in line 72.
Method makePlayer instantiates a new Player with a call to Manager method createPlayer. Class Manager provides static methods that enable programs to access most JMF resources. Method createPlayer opens the specified media source and determines the appropriate Player for the media source. Method createPlayer throws a NoPlayerException if an appropriate Player cannot be found for the media clip. An IOException is thrown if there are problems connecting to the media source.
ControllerListeners listen for the ControllerEvents that Players generate to track the progress of a Player in the media-handling process. Lines 170–171 register an instance of inner class PlayerEventHandler (lines 225–255) to listen for certain events that player generates. Class PlayerEventHandler extends class ControllerAdapter, which provides empty implementations of methods from interface ControllerListener. Class ControllerAdapter facilitates implementing
ControllerListener for classes that need to handle only a few ControllerEvent types.
Players confirm their progress while the processing media based on their state transitions. Line 174 invokes Player method realize to confirm all resources necessary to play media are available. Method realize places the Player in the Realizing state to indicate that it is connecting to and interacting with its media sources. When a Player
1248 |
Java Media Framework and Java Sound (on CD) |
Chapter 22 |
completes realizing, it generates a RealizeCompleteEvent—a type of ControllerEvent that occurs when a Player completes its transition to state Realized. This state indicates that the Player has completed all preparations needed to start processing the media. The program invokes method realizeComplete (lines 228–232) when
Player generates a RealizeCompleteEvent.
Most media players have a buffering feature, which stores a portion of downloaded media locally so that users do not have to wait for an entire clip to download before playing it, as reading media data can take a long time. By invoking Player method prefetch, line 231 transitions the player to the Prefetching state. When a Player prefetches a media clip, the Player obtains exclusive control over certain system resources needed to play the clip. The Player also begins buffering media data to reduce the delay before the media clip plays.
When the Player completes prefetching, it transitions to state Prefetched and is ready to play media. During this transition, the Player generates a ControllerEvent of type PrefetchCompleteEvent to indicate that it is ready to display media. The
Player invokes PlayerEventHandler method prefetchComplete (lines 235– 246), which displays the Player’s GUI in the frame. After obtaining the hardware resources, the program can get the media components it requires. Line 238 invokes method getMediaComponents (lines 206–222) to obtain the GUI’s controls and the media’s visual component (if the media is a video clip) and attach them to the application window’s content pane. Player method getVisualComponent (line 209) obtains the visual component of the video clip. Similarly, line 216 invokes Player method getControlPanelComponent to return the GUI’s controls. The GUI (Fig. 22.1) typically provides the following controls:
1.A positioning slider to jump to certain points in the media clip.
2.A pause button.
3.A volume button that provides volume control by right clicking and a mute function by left clicking.
4.A media properties button that provides detailed media information by right clicking and frame rate control by left clicking.
Look-and-Feel Observation 22.1
Invoking Player method getVisualComponent yields null for audio files, because there is no visual component to display.
Look-and-Feel Observation 22.2
Invoking Player method getControlPanelComponent yields different sets of GUI controls depending on the media type. For example, media content streamed directly from a live conference does not have a progress bar because the length of the media is not pre-de- termined.
After validating the new frame layout (line 241), line 244 invokes Player method start (line 239) to start playing the media clip.
Software Engineering Observation 22.1
If the Player has not prefetched or realized the media, invoking Player method start prefetches and realizes the media.