Java

Advanced Mutlimedia Supplements JSR 234
Technical Docs Apr 20, 2010
1

About This Article

This article introduces you to the Advanced Multimedia Supplements API (JSR 234) that extends the base Mobile Media API (JSR 135). Advanced Multimedia Supplements API (AMMS) adds many new controls, sub-packages and extensions enhancing the multimedia support on mobile devices.

This article provides an overview of the AMMS API. Sample code snippet demonstrating usage of different API is provided at the end of this article.

Scope:

This article is intended for MIDP developers wishing to develop AMMS based mobile applications. It assumes good knowledge of java programming language. This article focuses on JSR 234 and therefore explaining the Java technology is out of the scope in this article.

References:

1. JSR 234 Specification

http://jcp.org/en/jsr/detail?id=234

1. Advanced Multimedia

http://www.javaworld.com/javaworld/jw-08-2004/jw-0823-multimedia.html

Abbreviations:

Java ME Java Platform Micro Edition
CLDC Connection Limited Device Configuration
MIDP Mobile Information Device Profile

Introduction

Advanced Multimedia Supplements API (AMMS) adds many new Controls (in javax.microedition.amms.control and subpackages). Besides new Controls, several new extensions have also been added to the MMAPI framework (in javax.microedition.amms).

The set of new functionality provided by JSR 234 can be summarized by the following (some are mandatory and some are optional according to the specification):

  1. Music Capability: Equalizer and volume controls
  2. 3D Audio Capability: Support for 3D sound
  3. Image Encoding Capability: Support for encoding images
  4. Image Post-Processing Capability: Effects and transformations for images
  5. Camera Capability: Flash, focus, zoom functionality
  6. Tuner Capability: Tuner functions for the radio

API Description

AMMS API contains in all 7 packages, 2 classes and 41 interfaces. The following Table shows the packages classes and interfaces.

Table 1: javax.microedition.amms package Class Information.

Class Description
GlobalManager The GlobalManager handles the creation of EffectModules, SoundSource3Ds and   MediaProcessors.
Spectator Spectator represents the listener in the virtual acoustical space.

Table 2: javax.microedition.amms package Information.

Interface Description
EffectModule EffectModule is a logical group of Players and/or MIDI channels to which a   common sequence of effects can be applied.
MediaProcessor MediaProcessor is an interface designed to post-process different media   types.
MediaProcessorListener MediaProcessorListener is an interface that may be used to receive events  generated by a MediaProcessor.
Module Module is a logical group of Players and/or MIDI channels.
SoundSource3D SoundSource3D represents a sound source in a virtual acoustical space.

Table 3: javax.microedition.amms.control package Information.

Interface Description
AudioFormatControl AudioFormatControl controls the setting of the audio format.
ContainerFormatControl ContainerFormatControl controls the setting of the container formats.
EffectControl EffectControl is an interface for controlling an abstract filter with various   preset settings.
EffectOrderControl EffectOrderControl is an interface designed to specify the order of effects  represented by EffectControls.
FormatControl FormatControl controls the format used for storing media.
ImageFormatControl ImageFormatControl controls the setting of the image format.
MIDIChannelControl MIDIChannelControl is a Control that gives access to MIDI-channel-   specific  Controls.
PanControl PanControl is an interface for manipulating the panning of a Player in the  stereo output mix.
PriorityControl PriorityControl is an interface for manipulating the priority of a Player among  other Players.
VideoFormatControl VideoFormatControl controls the setting of the video format of the audio-  video format.

Table 4: javax.microedition.amms.control.audio3d package Information.

Interface Description
CommitControl CommitControl provides a mechanism to enable many audio  parameters to be updated simultaneously.
DirectivityControl DirectivityControl adds to OrientationControl a method for setting the  directivity pattern of a sound source.
DistanceAttenuationControl DistanceAttenuationControl is an interface for controlling how the  sound from a sound source is attenuated with its distance from the   Spectator.
DopplerControl DopplerControl is an interface for manipulating the settings of an effect  called Doppler.
LocationControl LocationControl is an interface for manipulating the virtual location of  an object (usually a SoundSource3D or the listener via the Spectator) in  the virtual acoustic space.
MacroscopicControl MacroscopicControl is an interface for manipulating the macroscopic  behavior of a sound source when using 3D audio.
ObstructionControl ObstructionControl provides a mechanism to control the overall level of  an audio signal flowing directly from a sound source to the Spectator.
OrientationControl OrientationControl is an interface for manipulating the virtual orientation  of an object in the virtual acoustical space.

Table 5: javax.microedition.amms.control.audioeffect package Information.

Interface Description
AudioVirtualizerControl AudioVirtualizerControl is an effect to virtualize audio channels.
ChorusControl ChorusControl is an interface for manipulating the settings of an audio effect  called chorus and its special case flanger.
EqualizerControl EqualizerControl is an audio EffectControl for manipulating the equalization  settings of a Player(s).
ReverbControl ReverbControl is an interface for manipulating the settings of an audio effect  called reverb.
ReverbSourceControl ReverbSourceControl is an interface for manipulating the feeding from an  object to the audio effect called reverb.

Table 6: javax.microedition.amms.control.camera package Information.

Interface Description
CameraControl CameraControl controls the features of the camera device.
ExposureControl ExposureControl controls the exposure settings of the camera device.
FlashControl FlashControl controls the flash of the camera device.
FocusControl FocusControl controls the focus of the camera device.
SnapshotControl SnapshotControl controls burst shooting with the camera.
ZoomControl ZoomControl controls the Optical and Digital Zoom (Magnification) of the digital  camera device.

Table 7: javax.microedition.amms.control.imageeffect package Information.

Interface Description
ImageEffectControl ImageFilter is an image effect that can be used to set various image filters  such as monochrome and negative.
ImageTonalityControl ImageTonalityControl is an effect that can be used to set various image  settings such as brightness, contrast and gamma.
ImageTransformControl ImageTransformControl is used to crop, zoom, mirror, flip, stretch and  rotate images.
OverlayControl OverlayControl controls the setting of overlay images on top of video or still  image.
WhiteBalanceControl WhiteBalanceControl is an image/video effect for altering the white  balance.

Table 8: javax.microedition.amms.control.tuner package Information.

Interface Description
RDSControl RDSControl is an interface for accessing the Radio Data System for VHF/FM sound  broadcasting (RDS) (BS EN 50067:1998) settings of a Player.
TunerControl TunerControl is an interface for controlling the tuner settings of a Player.

Overview

The AMMS is build on the Mobile Media API for J2ME (MMAPI) and therefore inherits the concepts of Players, to play both sound and video; the Manager, to create Players; and Controls, to interact with the various types of Players. AMMS adds many new Controls and 2 classes namely GlobalManager, Spectator. The relationship between AMMS API and MMAPI API is shown in figure 1.

GlobalManager class is used to create EffectModules, SoundSource3D and MediaProcessors. This is pretty much the same concept as in the Manager class that is used to create Players. Furthermore a Spectator class can be fetched from GlobalManager.

The idea behind GlobalManager is that it serves as a manager to all Player objects in the application. Players are usually grouped under some certain Module. Modules itself cannot be fetched from anywhere but its subclasses EffectModule and SoundSource3D are used instead. These two classes operate almost exactly the same way. The important difference between them is that EffectModule is meant for effects in general whereas SoundSource3D is meant only for three-dimensional audio effects.

Features

Camera Capability

Besides from taking picture from camera using MMAPI, AMMS API gives much more camera features. It provides more control on the way picture can be taken such as shutter feedback, camera rotation, exposure mode, image resolution, zoom control, flash control, snapshot controls.

CameraControl, FlashControl, WhiteBalanceControl, ZoomControl, ExposureControl, FocusControl, SnapshotControl can be used for accessing camera capabilities. Access to the device's camera function is through a call to Manager.createPlayer("capture://video") or other parameter that access camera, and then by getting Controls on the Player returned.

CameraControl

CameraControl camera = (CameraControl)
                 player.getControl("javax.microedition.media.control.camera.CameraControl");

if(camera!=null) {

     camera.enableShutterFeedback(true);// Toggles the native shutter sound and visual
     //shutter feedback on and off.

     int rotation = camera.getCameraRotation();

     boolean portrait = false;
     if(CameraControl.ROTATE_LEFT==rotation||CameraControl.ROTATE_RIGHT==rotation)
     portrait = true; // And then perhaps do something different with the image

     String[] exposureModes = camera.getSupportedExposureModes();//Returns a list of exposure modes
     // supported by the camera device
     
    camera.setExposureMode(exposureModes[2]); // Pick one

     int[] resolutions = camera.getSupportedStillResolutions();//supported still resolutions as  
     //x, y pairs. For example, if the camera supports 1024x768
     //and 640x480 still resolutions, [1024, 768, 640, 480] will be returned.

     camera.setStillResolution(1); // Pick the second pair (w, h)

}

FlashControl

FlashControl flash = (FlashControl)
player.getControl("javax.microedition.media.control.camera.FlashControl");
if(flash!=null) {
    int[] modes = flash.getSupportedModes();//Returns a list of flash modes 
    supported by the camera device.
    flash.setMode(FlashControl.AUTO_WITH_REDEYEREDUCE);
}

WhiteBalanceControl

WhiteBalanceControl white = (WhiteBalanceControl)
player.getControl("javax.microedition.media.control.camera.WhiteBalanceControl");
if(white!=null) {
    String[] presets = white.getPresetNames();//Gets the available preset names.
    white.setPreset("tungsten"); // Picked from list
    int kelvin = white.getColorTemp(); // for display to user
}

ZoomControl

ZoomControl zoom = (ZoomControl)
player.getControl("javax.microedition.media.control.camera.ZoomControl");
if(zoom!=null) {
    // the values of the zoom are multiplied by 100
    int max = zoom.getMaxOpticalZoom(); // e.g., 200 for 2x
    int levels = zoom.getOpticalZoomLevels(); // e.g., 3 levels - 1x, 1.5x and 2x
    zoom.setOpticalZoom(140); // Request the closest level to 1.4x, which will be 1.5x
    zoom.setOpticalZoom(ZoomControl.NEXT); // Zoom in to 2x
}

ExposureControl

ExposureControl exposure = (ExposureControl)      
player.getControl("javax.microedition.media.control.camera.ExposureControl");
if(exposure!= null) {
    exposure.setExposureTime(2); // Sets the shutter speed.
    exposure.setFStop(280);// Sets the aperture.
    exposure.setISO(200);// The common values are ISO 100, ISO 200, and ISO 400.
}

FocusControl

FocusControl focus = (FocusControl)
player.getControl("javax.microedition.media.control.camera.FocusControl");
if(focus!=null) {
     if(focus.isAutoFocusSupported()) {
        focus.setFocus(FocusControl.AUTO);
     } else {
        // Otherwise, try the "mountain" or infinity setting. Find out what was actually 	//set.
        int focusSet = focus.setFocus(Integer.MAX_VALUE);
     }
}

SnapshotControl

SnapshotControl snapshot = (SnapshotControl)
player.getControl("javax.microedition.media.control.camera.SnapshotControl");
    if(snapshot!=null){
        snapshot.setDirectory("/SDCard");
         snapshot.setFilePrefix("hols");
        snapshot.setFileSuffix(".jpg");
        if(burstShooting) {
        // Start burst shooting, maximum 20 pictures
        snapshot.start(20);
    } else {
        // Take one picture and allow the user to keep or discard it
        snapshot.start(ShapshotControl.FREEZE_AND_CONFIRM);
        // ...
        // PlayerListener got a WAITING_UNFREEZE event and the user chose to discard the 	//picture
        snapshot.unfreeze(false);
    }
}

Image Post-Processing Capability

The Image Post processing capability allows image transformations i.e. manipulation of images after they have been taken. MediaProcessor is an interface designed to post-process different media types. It is intended that a MediaProcessor generally exposes various EffectControls (to configure the processing behavior) and FormatControls (to set the output format).

Using a MediaProcessor it is possible to specify source media and several post-processing effects to be applied on it. MediaProcessor has four different states: UNREALIZED, REALIZED, STARTED and STOPPED. The following figure 2 depicts the most important state transitions in the lifecycle of the MediaProcessor as a directed graph. For clarity, the diagram does not cover all possible transitions and exceptions.

For example processing an image is done by the following steps:

  1. Create a media processor
  2. Configure the media processor using available controls
  3. Instruct the media processor to start processing the image (synchronously or asynchronously). synchronously using complete() and asynchronously using start() and MediaProcessorListener.

Below is shown a simple example where a JPEG image is converted into a monochrome image.

MediaProcessor mp = GlobalManager.createMediaProcessor("image/jpeg");
InputStream inputStream = ... // create a InputStream that contains the source image
OutputStream outputStream = ... // create a OutputStream that will receive the resulting 
//image
mp.setInput(inputStream);
mp.setOutput(outputStream); 
// Define effects to be applied during processing
ImageEffectControl imageEffect =  (ImageEffectControl)
mp.getControl("javax.microedition.amms.control.imageeffect.ImageEffectControl");
imageEffect.setPreset("monochrome");
// Set output format
ImageFormatControl fc = (ImageFormatControl)
mp.getControl("javax.microedition.amms.control.ImageFormatControl");
fc.setFormat("image/jpeg");
fc.setParameter("quality", 80);
// Do the actual processing. If you do not want to use a blocking call, 
// use start() and MediaProcessorListener.
mp.complete();

When having an instance of the media processor, you can retrieve the following controls to perform image processing and encoding using:

ImageEffectControl imageEffect = (ImageEffectControl)
mp.getControl"javax.microedition.amms.control.imageeffect.ImageEffectControl");

ImageTonalityControl imageTonality = (ImageTonalityControl)
mp.getControl"javax.microedition.amms.control.imageeffect.ImageTonalityControl");

ImageTransformControl imageTransform = (ImageTransformControl)
mp.getControl"javax.microedition.amms.control.imageeffect.ImageTransformControl");

OverlayControl overlay = (OverlayControl)
mp.getControl("javax.microedition.amms.control.imageeffect.OverlayControl");

WhiteBalanceControl whiteBalance = (WhiteBalanceControl)
mp.getControl("javax.microedition.amms.control.imageeffect.WhiteBalanceControl");

ImageFormatControl imageFormat=(ImageFormatControl)
mp.getControl("javax.microedition.amms.control.ImageFormatControl");

All the different controls have different methods for querying and setting possible values. For a complete list of functions please have a look in the JCP JSR 234 documentation. Common for all the controls is that they must be enabled by the call "setEnabled(true)" to be executed.

An example using the ImageEffectControl could look like this:

String[] preset_names = imageEffect.getPresetNames();
//…//
imageEffect.setPreset(choice);
imageEffect.setEnabled(true); 

Tuner Capability

Access to the device's radio function is through a call to Manager.createPlayer("capture://radio") to access radio, and then by getting Controls on the Player returned. Once the player is created, the following controls can be retrieved for the extended tuning functionality:

TunerControl tunerControl = (TunerControl)
player.getControl("javax.microedition.amms.control.tuner.TunerControl");

RDSControl rdsControl = (RDSControl)
player.getControl("javax.microedition.amms.control.tuner.RDSControl");

For example we use the TunerControl to find an FM radio station above 91 MHz, set the station to play in stereo, save it in a preset slot, and then switch to another preset:

TunerControl tuner = (TunerControl)
player.getControl("javax.microedition.media.control.tuner.TunerControl");
int frequencyFound = tuner.seek(910000, TunerControl.MODULATION_FM, true);
tuner.setStereoMode(TunerControl.STEREO);
tuner.setPreset(1);
tuner.setPresetName(1, "Radio 1");
if(tuner.getNumberOfPresets()>=2) {
      tuner.usePreset(2);
      int secondFrequency = tuner.getFrequency(); // For display to user
      String modulation = tuner.getModulation(); // For display to user
}

RDSControl gives access to the RDS data on the selected FM frequency. Here we extract some information for display to the user and then turn off the automatic traffic announcement switching.

RDSControl rds = (RDSControl)
 radio.getControl("javax.microedition.media.control.tuner.RDSControl")
if(rds!= null) {
 Date date = rds.getCT();
 boolean ta = rds.getTA();
 String ps = rds.getPS();
 String pty = rds.getPTYString(true);
 rds.setAutomaticTA(false);
}

Music Capability

The music capability provides Controls to modify the audio sounds when listening to music—equalization and panning. VolumeControl from MMAPI is also available. Here we fetch the equalization presets available and let the user chooses one:

EqualizerControl equalizer = (EqualizerControl)
player.getControl("javax.microedition.media.control.audioeffect.EqualizerControl");
String[] presets = equalizer.getPresetNames();
equalizer.setPreset("rock"); // Pick one

More sophisticated settings are available—for example, bass and treble levels. Here we set the bass level to flat/normal (50) and then turn the treble all the way up (100):

equalizer.setBass(50);
equalizer.setTreble(100);

For more fine-grained control over the sound, the device may support multiband equalization—how many bands are available and what they can be set to is up to the device:

int numberOfBands = equalizer.getNumberOfBands();
int minLevel = equalizer.getMinBandLevel();
int maxLevel = equalizer.getMaxBandLevel();

Next we can find out the frequencies of the first two bands for display to the user:

int firstBandFrequency = equalizer.getCenterFreq(0);
int secondBandFrequency = equalizer.getCenterFreq(1);

And if we want to turn the voice frequencies up to the maximum, we find the band that has the most effect on 3 kHz and turn it up:

int bandNumber = equalizer.getBand(3000000);
if(bandNumber!=-1) {
 equalizer.setBandLevel(maxLevel, bandNumber);
}

3D Audio Capability

The 3D audio capability is probably the most difficult to understand since it is not something commonly used (unlike a digital camera or an equalizer), and the programming itself is quite complex. The API allows the programmer to construct a network of Players that can be combined and fed into effects, and then output to the user. Traditional 2D effects like chorus and equalization are supplemented by 3D effects that attempt to place sound sources in a virtual 3D space around the listener. Note that there is some discussion going on in the expert group about this part of the specification and an alternative proposal exists, which is included with the draft specification download.

In the following examples, Players p1, p2, and p3 are created with different sounds using calls to Manager.createPlayer("..."). p1 has been set up as a 3D sound source using SoundSource3D and move it in 3D space using LocationControl (which must be supported), then set how the sound attenuates as it travels through space to our listening position, which we'll define later:

SoundSource3D source = GlobalManager.createSoundSource3D();
source.addPlayer(p1);
LocationControl locationSource = (LocationControl)
source.getControl("javax.microedition.media.control.audio3d.LocationControl");
lcationSource.setCartesian(0, 0, -10000); // 10 meters in front (negative z axis)
DistanceAttenuationControl distanceSource = (DistanceAttenuationControl)
source.getControl("javax.microedition.media.control.audio3d.DistanceAttenuationControl");
distanceSource.setParameters(10, 50000, true, 1000);

Last, we define how much of this sound is fed to the reverb effect—in this case -2 dB

if((ReverbSourceControl reverbSource = (ReverbSourceControl)
source.getControl("ReverbSourceControl")) != null) {
reverbSource.setLevel(-200);
}

Now we set up some 2D effects. Players p2 and p3 are fed into an EffectModule, which then applies a flanger effect on both of them and fine-tunes the preset. The controls available from an EffectModule depend on the Players attached to them; ChorusControl may be supported:

EffectModule effect = GlobalManager.createEffectModule();
effect.addPlayer(p2); effect.addPlayer(p3);
ChorusControl chorusEffect = (ChorusControl)
effect.getControl("javax.microedition.media.control.audioeffect.ChorusControl");
if(chorusEffect!=null) {
  String[] presets = chorusEffect.getPresets();
  chorusEffect.setPreset("flanger"); // Pick one
chorusEffect.setModulationDepth(4000);
chorusEffect.setModulationRate(260);
}

And again we define the feed from this EffectModule to the reverb effect—in this case -1 Db

if((ReverbSourceControl reverbEffect = (ReverbSourceControl)
effect.getControl("ReverbSourceControl")) != null) {
reverbEffect.setLevel(-100);
}

We can move the listener's position in this 3D space by using the GlobalManager's Spectator ("spectator" applies to audio here, as the term "listener" is used in Java in too many other situations). Again, we use the LocationControl and also add the OrientationControl set to 10 degrees heading, 0 degrees pitch, and 5 degrees roll so the Spectator "looks" slightly away from the negative z axis:

Spectator spectator = GlobalManager.getSpectator();
LocationControl locationSpectator = (LocationControl)
spectator.getControl("javax.microedition.media.control.audio3d.LocationControl");
locationSpectator.setCartesian(0, 0, 0); // The origin (default)
OrientationControl orientationSpectator = (OrientationControl)
spectator.getControl("javax.microedition.media.control.audio3d.OrientationControl");
orientationSpectator.setOrientation(10, 0, 5);

Finally, all those ReverbSourceControl feeds are input to the master reverb that we configure:

ReverbControl reverb = (ReverbControl)
GlobalManager.getControl("javax.microedition.media.control.audioeffect.ReverbControl");
reverb.setPreset("alley");
reverb.setEnabled(true);
reverb.setLevel(80);
reverb.setTime(4000);

Detecting AMMS API presence

To check whether the handset support AMMS API, System.getProperty("microedition.amms.version") can be used. If it is supported, the AMMS version is returned else null will be returned.

System Properties

Following are some of the System Properties that can be used to query the API.

Key Description
supports.mediacapabilities AudioVirtualizerControl The String returned specifies the supported  capabilities, delimited by one.The possible values are: music,  audio3d, imageencoding, imagepostprocessing, camera, tuner.
tuner.modulations The String returned specifies the supported tuner modulation   settings for which a Player can be created. Returned modulations  are delimited by one whitespace. If no modulations are supported,  the tuner.modulations returns null. TunerControl specifies the  following constants, but supported modulations are not limited to  these:fm for FM audio radio and am for AM audio radio.
audio.samplerates The String returned specifies the recommended audio sampling  rates in Hertzs, delimited by one whitespace.
audio3d.simultaneouslocations The String returned specifies the maximum number of   SoundSource3D modules that the application is recommended to  have active simultaneously.
camera.orientations The String returned specifies the orientations of the cameras of the  device. The String consists of orientations per device, delimited by  one whitespace. The orientation values can be the following: -  inwards (The camera is pointing towards the user when the device  is held in a natural way.) -outwards (The camera is pointing away  from the user when the device is held in a natural way. -unknown  (The pointing direction of the camera is user configurable or   cannot  be known for some other reason.) If no cameras are  supported, the camera.orientations returns null. Default camera  (capture://video) is listed first in the String.
camera.resolutions The String returned specifies the sensor sizes of the cameras of  the device. The String  consists of sensor  sizes  per device,  delimited by one whitespace.  An  example of  a   returned String: "devcam0:1024x768 devcam1:640x480". If no  cameras are  supported, the camera.resolutions returns  null. Default camera (capture://video) is listed first in the String.

Security & Permissions

Some methods in this API are defined to throw a SecurityException if the user does not have the permissions needed to perform the action. Following Table shows the permissions associated with AMMS API.

Permissions name Methods protected by this Permission
javax.microedition.amms.control.camera CameraControl.enableShutterFeedback().
javax.microedition.amms.control.camera SnapshotControl.setDirectory(java.lang.String   directory).
javax.microedition.amms.control.camera SnapshotControl.start(int maxShots).
javax.microedition.amms.control.tuner.setPreset TunerControl.setPreset(int preset)   TunerControl.setPreset(int preset, int freq,   java.lang.String mod, int stereomode)  TunerControl.setPresetName(int preset,  java.lang.String name) .

Tuner MIDlet

Class: TunerMidlet

import javax.microedition.lcdui.Display;
import javax.microedition.midlet.*;
public class TunerMidlet extends MIDlet {
 public void startApp() {
       Display display = Display.getDisplay(this);
       TunerExample te = new TunerExample();
       	      display.setCurrent(te.form);
  	}

 public void pauseApp() {
  	}

 public void destroyApp(boolean unconditional) {
 }
}

Class: TunerExample

import javax.microedition.media.*;
import javax.microedition.media.Control.*;
import javax.microedition.amms.control.tuner.*;
import java.util.Date;
import javax.microedition.lcdui.Form;

public class TunerExample {

  public Player radioPlayer;
  public TunerControl tunerControl;
  public RDSControl rdsControl;
  public Form form;

  public TunerExample()
  {
      form = new Form("Radio Test");
      initializeRadio();
}

  /**
   * Initializes and switched on the radio.
   */
  public void initializeRadio() {
    try {
      radioPlayer = Manager.createPlayer("capture://radio");
      radioPlayer.realize();
      radioPlayer.addPlayerListener(new MyPlayerListener(this));
      tunerControl = (TunerControl)
        radioPlayer.getControl("javax.microedition.amms.control.tuner.TunerControl");
      tunerControl.setStereoMode(TunerControl.STEREO);
      // Then, let's get the RDSControl:
      rdsControl = (RDSControl)
        radioPlayer.getControl("javax.microedition.amms.control.tuner.RDSControl");
      if(rdsControl != null) {
        //Let's turn on the automatic switching
        //to possible traffic announcements:
        rdsControl.setAutomaticTA(true);
      }
      radioPlayer.start();
      // Now that the radio is on let's first find a radio station
      // by seeking upwards from 91.0 MHz:
      int freq = tunerControl.seek(910000, TunerControl.MODULATION_FM, true);
      if(freq==0) {
        // no FM broadcasting found, do some error handling here...
        return;
      }
    } catch (Exception ioe) {
        form.append("initializeRadio ioe "+ioe);
    }
  }

  /**
   * Shows on the console some RDS data.
   * This method is called from MyPlayerListener.
   */
  public void updateRDSDisplay() {
    if(rdsControl != null) {
      String channelName = rdsControl.getPS();
      String radioText = rdsControl.getRT();
      String programmeType = rdsControl.getPTYString(true);

      // update the application UI to show the information:
      form.append(" updateRDSDisplay channelName "+channelName + ", radioText " +         
        radioText);
      form.append("genre:" + programmeType);
      int freq = tunerControl.getFrequency();
      form.append("freq:" + freq);
      Date date = rdsControl.getCT();
      if(date != null) {
        form.append("The local time is " + date);
      }
    }
  }
}

/**
 * Listens RDS_NEW_DATA events and calls TunerExample.updateRDSDisplay
 * when such an event is received.
 */
class MyPlayerListener implements PlayerListener {
  TunerExample tunerExample;

  public MyPlayerListener(TunerExample tunerExample) {
    this.tunerExample = tunerExample;
  }

  public void playerUpdate(Player player,
                           java.lang.String event,
                           java.lang.Object eventData) {
    if(event == RDSControl.RDS_NEW_DATA) {
      tunerExample.updateRDSDisplay();
    }
  }
}

Downloads

This article can also be downloaded in Word Document and PDF format . Click on the following link to download :
Advanced Multimedia Supplements