Chapter 38

Creating On-Demand Multimedia Services

by George Menyhert


CONTENTS

The World Wide Web has served as an agent of change for many industries. Even old, stable technologies like telephone service are swaying to the rhythm of the Net. Very shortly, the content we now call multimedia will be available as an on-demand stream, first to your desktop, then to your set top, and finally to your palmtop. The promise is that you will receive the content of the exact type you want, as much as you want, anywhere you want.

Java will probably play an important role in this media explosion. If ever there was a right programming language in the right place at the right time, this surely looks like it. Pay-Per-View and Content On-Demand are terms that you are probably already familiar with. Java holds the promise of creating high quality products for these new application areas.

Java's Suitability for On-Demand Applications

Why is Java particularly suited for on-demand access of multimedia over the network? Take a look at the process of doing an on-demand multimedia application using C++.

The following shows your list of concerns if developing a multimedia application using C++:

On the server Side:

On the client Side:

The server application can be fairly platform-independent; however, it has platform-specific modules controlling the file system and other operating system-specific aspects. It also needs basic knowledge of the underlying media if it is to transfer the data efficiently (can the headers be left out, what data packing is most appropriate?).

The client software is very platform-specific. At best, the user interface uses a standard library that can be linked on different platforms. More likely, sections of it need to be rewritten for the various platforms. The client also needs to control the output device and understand the translation, if any, between the file data format and the required hardware data format. The client needs intimate knowledge of network communications. Finally, the client needs to be distributed to customers; this is a major marketing problem. The customer wants the audio or video "on-demand" (read now). Can you imagine an on-demand system where users need to have the foresight to order an application a couple of days before they have the desire to watch and listen?

There are some libraries available for C++ that help alleviate some of the problems-a commercial implementation of CORBA for the communications issues, various UI libraries for the user interface-but none deal comprehensively with the problem areas of network multimedia.

Java addresses many of these problems. The underlying steps remain, but the Java execution environment removes many of the implementation details from the developer. For example, instead of developing a server from scratch (or even modifying and reusing an existing server), the product can be developed as an applet. The communication issues are completely removed from the process. There is no need to develop a server at all. Any off-the-shelf Web server works.

Any application (or applet) developed with Java is platform-independent. Therefore, creating graphical elements, displaying images, playing audio, and processing events are not only done with the same source code, but the same compiled binary code.

The Java built-in media API removes many file format- and output hardware-dependent issues. For example, audio clips can be streamed over the network and played on any system without regard to the various output devices or streamed data formats.

Because the majority of the underlying functionality is supplied by the Web server/browser system, the distributed Java executable is very small. The example developed for this chapter is approximately 9K. Due to its extremely compact size, it can be downloaded over the Web in less time than most images. This solves the problem of distribution and provides instant access.

To review, Java is suitable for multimedia because:

Using the On-Demand Audio Applet

This applet is not intended to be a commercial On-Demand audio server. It is a simple example of how audio can be added to an applet.

Logging In

To login to the On-Demand Audio Applet:

  1. Start your favorite Java-capable browser.
  2. Open the file OnDemand.html with your browser.
    The text string Applet OnDemand running is displayed on your browser's status line when the applet is fully loaded. The login dialog appears as in Figure 38.1.
  3. Click in the Username text field.
  4. Enter the text string anonymous in lowercase letters.
  5. Click the Login button.

Figure 38.1 : Enter anonymous in the Username text field.

Playing Audio Clips

To play audio clips:

  1. Double-click the name of the Artist.
    A list of the artist's songs appears in the Songs list.
  2. Double-click the name of the song that you want to play.
    Wait for a few moments. It takes a while for the audio clips to load. Copyright and other facts appear in the Information list when the song is loaded (see Figure 38.2).
  3. Use the audio controls Play, Loop, and Stop to control the audio stream.

Figure 38.2 : The OnDemand applet is ready to play an audio stream.

Adding Sound to Applets

Adding sound to a Java applet is extremely simple. There are only two steps: Identify the audio source, and play the clip. In general, the audio functionality is only available via the applet class. Although it is possible to run an applet as an application, there are many limitations to applets executed in this mode (including media streaming). However, there are some available work-arounds. See Chapter 13, "Running Applets as Applications," for details about the techniques and limitations of running applets as applications and ways of overcoming these limitations.

To specify the source of the sound clip, use the applet method getAudioClip. It requires one or two arguments-either a base URL and a relative file path packed as a String, or a complete URL. For example, to attach an AudioClip object to an audio file stored in a folder in your applet's HTML location, try the following:

AudioClip rockinTune = this.getAudioClip(getDocumentBase(), 
"rocking.au");

Tip
Getting the audio clip this way is usually very slow the first time it is done in an applet. This is due to dynamic class loading.
When you are running these applets over the Internet, each instantiation of an AudioClip is extremely slow. This is because the AudioClip object does not truly stream the audio data. It downloads and buffers the data at the time of instantiation.
You need to give users some feedback so they don't cancel the operation. Try a call to showStatus that states something like, "Initializing audio. Please wait…". Changing the cursor to a wait state would be ideal, but is not possible in applets.

getAudioClip returns a reference to an AudioClip object. You can then use this object to play the audio clip when you are ready. To do this, simply call the AudioClip.play method

rockinTune.play();

You can also stop the playback using AudioClip.stop method and play back continuously using the AudioClip.loop method.

Caution
The supported list of audio file formats is limited. Currently, you can use only 8-bit, 8000Hz, single-channel (mono) Next/Sun AU files with G711 m-law compression. Note that files with a higher sample rate may produce hissing on playback.

On-Demand Music Applet Code Review

Playing audio in an applet over the network involves only two method calls. It is simple to expand on this to create a fully functional online, on-demand music applet (see the previous section, "Using the On-Demand Audio Applet"). There are four basic elements to this on-demand music applet:

The first three elements are addressed here. The fourth element involves writing to files on the server and is addressed in Chapter 8, "Reading and Writing Files from an Applet." The sample code does have comments showing where to implement the transaction registration.

Applet Architecture

To keep the system as flexible as possible, all of the applet options are controlled by configuration files and parameters in the applet HTML. There are four parameters. Each parameter is the name of a configuration file. They are:

Specifying the file names as parameters and designing the applet to be based on configuration files allows a single, simple applet to be used by a wide variety of users without any code modification by the programmer. All flexible values are specified in the files-the image file, the acceptable user names, the list of artists, the names of the files containing the songs for each artist, the names of the audio files associated with each song, and the detailed information for each song. These can be easily modified and don't even require the user to reload the applet.

Due to the simplicity of this applet, there is no need to generate a host of new classes. The sample includes a total of two new classes: one subclass of applet, and a utility class that aids in file input and string parsing (FileParser). If the applet were expanded, separate classes would probably be desirable for each element listed earlier.

Initialization and Registration

First, the applet performs initialization, and the registration interface is prepared. During initialization, the applet reads the required filenames from the parameter list. Also, an Image object is created using one of the parameters as a filename. Finally, the rest of the user interface is created and organized (see Listing 38.1). The applet then waits for events. See the OnDemand.init method in the OnDemand.java source file on the CD.

Here, the initialization parameters are specified in the HTML.


Listing 38.1  Initialization Parameters in the HTML
<APPLET code="OnDemand.class" width=600 height=300>
<PARAM name="userfile" value="user.txt">
<PARAM name="imagefile" value="image.gif">
<PARAM name="artistsfile" value="art.txt">
<PARAM name="transactionfile" value="tran.txt">
</APPLET>
...

First, the initialization parameters are set, then an image is read, as shown in Listing 38.2.


Listing 38.2  Reading the Initialization Parameters and Creating the Image Object in the Java Applet
// get the input parameters
userFileName = getParameter("userfile");
imageFileName = getParameter("imagefile");
artistFileName = getParameter("artistsfile");
transactionFileName = getParameter("transactionfile");
...

// get the startup image
startUpImage = getImage(getDocumentBase(),imageFileName);

...

When the Login button is pressed, the method OnDemand.confirmLogin is called. It retrieves the requested user name from the text field, reads the contents of the user file (specified in the parameter list), and compares the selected name to the retrieved list (see Listing 38.3). If the name matches, the interface is cleared and OnDemand.startUI is called to begin the main program. If the name does not match one of the names in the configuration file, the text field is cleared and the login form remains on the screen.

Tip
To improve performance, user configuration files could be read asynchronously at startup.

Note
This applet is not intended as a commercial application; a more sophisticated applet uses encryption or digital signatures to secure its communications (see Chapters 26-28 in Part VI, "Java Security," for more details). It also provides a dialog box if the login fails, and a password is then required. To implement a password text field, see TextField.setEchoCharacter.


Listing 38.3  Confirming the Username
// get the specified UID
userName = userNameField.getText();
...
// read the file contents and pack the lines of text into a
// vector of strings
userFileContents = FileParser.parseFile(getDocumentBase(),
                          userFileName);

...
// loop over the acceptable usernames and compare the specified UID
int i;
int total = userFileContents.size();
for(i=0; i<total; i++) {

 try {
 String tempString = (String)userFileContents.elementAt(i);

 // compare the strings
 if( userName.compareTo(tempString)
 == 0) {
     
 // the strings are the same, let them log in
 startUI();
     
 return;
 }

 }
 catch (ArrayIndexOutOfBoundsException e) {
 // do nothing since we are sure not to be out of the bounds
 }
}

...

Song Selection

Once the user is logged in, two text lists are displayed. The first is a list of artists; the second is a list of songs by that artist. The first list is read from the artist file (one of the initialization parameters). When an artist is selected, OnDemand.selectArtist is called and the artist's line from the configuration file is parsed and the song list filename is retrieved. Then, the song list is read (see Listing 38.4).


Listing 38.4  Reading the Song List in Response to an Artist Being Selected
...

//
// get the selected artist
//
int index = artistList.getSelectedIndex();

...

// get the selected artist configuration line
String temp = (String)artistFileContents.elementAt(index);

//
// read the contents of the artist's song file. the name of the
// song file is the second argument in the artists file.
//
songFileContents = FileParser.parseFile(getDocumentBase(),
                          FileParser.parseField(temp,2));
...

When a song is selected, OnDemand.selectSong is called, the song's configuration line is parsed, and the song filename and informational message is retrieved. Then, the song information is displayed using the song filename retrieved from the configuration files; the AudioClip object is created (see Listing 38.5).


Listing 38.5  Parsing the Song Configuration Line
//
// get the selected song from the list
//
int index = songList.getSelectedIndex();

// notify the user of wait condition
showStatus("Initializing audio. Please wait...");
...

// get the song info string the song's configuration line
String line = (String)songFileContents.elementAt(index);

//
// create the audio clip
//
sound = getAudioClip(getDocumentBase(),
           FileParser.parseField(line,2));

//
// populate the text area
//
FileParser.populateTextArea(songInfo,
                FileParser.parseField(line,3),
                songInfo.getColumns()-10);
...

Caution
Double-clicking is used in this example to select items from the list. This can be confusing since one click highlights a new item. If the user is not paying attention, there may be confusion between which clip is selected and which is highlighted. To alleviate this problem, subclass List and override the handleEvent operation. Look for the event IDs of Event.LIST_SELECT and Event.LIST_DESELECT with the target a list region. See the Java API documentation for details.

Playing the Songs

Once a song is selected, there is little remaining to do. If the user presses any of the audio control buttons (play, stop, loop), the appropriate AudioClip command is executed. If the action is play or loop, OnDemand.logTransaction is called to log the information of the transaction. In the example, logTransaction is a stub with comments in it to aid in later implementation.

Java Shortcomings

Although Java is a very powerful language, there are a number of things that can be improved:

New Features

Java is evolving; look for the following changes that will affect the development of multimedia applications: