Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Java How to Program, Fourth Edition - Deitel H., Deitel P.pdf
Скачиваний:
58
Добавлен:
24.05.2014
Размер:
14.17 Mб
Скачать

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.