For information about the design and functionality of the MIDlet, see section Design.
The MediaList
view is created and displayed by
the MediaSamplerMIDlet
class. A reference of MediaSamplerMIDlet
is passed to all LCDUI elements used
by the application (MediaList
, AudioCanvas
, VideoSourceSelector
, and so on). The reference
is used for getting the display and for displaying an alert when an
error occurs. MediaList
creates and displays the
classes AudioCanvas
, VideoSourceSelector
, SupportForm
, and DRMPlayer
.
The MediaFactory
class provides media-specific
information such as available sound and video medias, and their MIME
types and file paths in the MIDlet package (JAR file). MediaFactory
reads resource-specific file path properties from the application
descriptor (JAD file). Data information returned from MediaFactory
is encapsulated in the Media
class.
UI classes in the viewer
package display the UI
or route to another display.
For more information about the key aspects of implementing the MIDlet, see:
The following code shows the method for loading
resources as InputStream
objects:
public InputStream getInputStream() throws IOException { if (location == LOCATION_JAR) { return getClass().getResourceAsStream(file); } else if (location == LOCATION_HTTP) { return urlToStream(file); } throw new IOException("Not supported location type!"); }
The following code shows the method for fetching
content from a specified HTTP URL in the form of InputStream
objects:
private InputStream urlToStream(String url) throws IOException { // Open connection to the http url... HttpConnection connection = (HttpConnection) Connector.open(url); DataInputStream dataIn = connection.openDataInputStream(); byte[] buffer = new byte[1000]; int read = -1; // Read the content from url. ByteArrayOutputStream byteout = new ByteArrayOutputStream(); while ((read = dataIn.read(buffer)) >= 0) { byteout.write(buffer, 0, read); } dataIn.close(); // Fill InputStream to return with content read from the URL. ByteArrayInputStream byteIn = new ByteArrayInputStream(byteout.toByteArray()); return byteIn; }
ToneControl
is the interface
that enables playback of a user-defined monotonic tone sequence:
public static byte[] getToneSequence() { byte[] sequence = {ToneControl.VERSION, 1, ToneControl.TEMPO, 30, // times 4 = 120 beats-per-minute ToneControl.C4, 16, ToneControl.C4 + 2, 16, // D4 ToneControl.C4 + 4, 16, // E4 ToneControl.C4 + 5, 16, // F4 (note E# does not exist) ToneControl.C4 + 7, 16, // G4 ToneControl.C4 + 9, 16, // A4 ToneControl.C4 + 11, 16, // B4 ToneControl.C4 + 9, 8, // A4 ToneControl.C4 + 7, 8, // G4 ToneControl.C4 + 5, 8, // F4 (note E# does not exist) ToneControl.C4 + 4, 8, // E4 ToneControl.C4 + 2, 8, // D4 ToneControl.C4, 8,}; return sequence; }
PlayerPool
is a class that handles
audio player pooling and playing. DRMPlayer
plays
DRM-protected audio files.
The following code shows the method for adding media to a pool:
public void addMedia(Media media) throws MediaException { String mimeType = media.getType(); if (!isMediaSupported(mimeType)) { throw new MediaException("Type " + mimeType + " is not supported!"); } addSoundObject(media); }
The following code shows the method for adding a tone sequence:
public void addToneSequence(byte[] sequence) throws MediaException { if (!isMediaSupported("audio/x-tone-seq")) { throw new MediaException("Tone (audio/x-tone-seq) is not supported!"); } addSoundObject(sequence); }
The following code shows the method for checking whether the media MIME type is supported by the device:
public boolean isMediaSupported(String mimeType) { String[] types = Manager.getSupportedContentTypes(null); for (int i = 0; i < types.length; i++) { if (mimeType.toLowerCase().equals(types[i].toLowerCase())) { return true; } } return false; }
The getSupportedContentTypes
method returns the
list of supported content types for the given protocol.
The following code shows the method for adding sound objects:
private void addSoundObject(Object sndObject) throws MediaException { if (!supportMultiPlayer) { medias.addElement(sndObject); } else { try { Player player = createPlayer(sndObject); players.addElement(player); medias.addElement(sndObject); } catch (MediaException se) { // Let's assume that second player creation failes even media // type should be supported. if (supportMultiPlayer && players.size() == 1) { Player failedPlayer = (Player) players.elementAt(0); discardPlayer(failedPlayer); players.removeElementAt(0); try { Player player = createPlayer(sndObject); // Assuming that Player creation works if there is not other // instances, we let the pool work in single Player instance mode. supportMultiPlayer = false; medias.addElement(sndObject); // Update player vector to contain only current. players.removeAllElements(); players.addElement(player); realizedSoundIndex = medias.size() - 1; } catch (MediaException me) { // Cannot create player. throw me; } catch (IOException ioe) { midlet.alertError("IOException: " + ioe.getMessage()); } } else { // Reject this media and route Exception to method caller. throw se; } } catch (IOException ioe) { midlet.alertError("IOException: " + ioe.getMessage()); } } }
The Player
class controls the
rendering of time-based media data. It provides the methods to manage
the Player's
lifecycle, controls the playback progress,
obtains the presentation components, and controls and provides the
means to synchronize with other Players
.
The
following code shows the methods for creating and initializing the Player
with Object
, Media
, and byte[]
parameters:
private Player createPlayer(Object media) throws MediaException, IOException { if (media instanceof byte[]) { return createTonePlayer((byte[]) media); } return createPlayer((Media) media); } // ... private Player createPlayer(Media media) throws MediaException, IOException { InputStream is = media.getInputStream(); String mediaType = media.getType(); Player player = Manager.createPlayer(is, mediaType); player.addPlayerListener(this); player.realize(); player.prefetch(); return player; } // ... private Player createTonePlayer(byte[] sequence) throws MediaException, IOException { Player player = Manager.createPlayer(Manager.TONE_DEVICE_LOCATOR); player.addPlayerListener(this); player.realize(); ToneControl tc = (ToneControl) (player.getControl("ToneControl")); tc.setSequence(sequence); return player; }
The Manager
class is the access
point for obtaining system dependent resources, such as Players
, for multimedia processing. The createPlayer
method creates a Player
from an input locator. The addPlayerListener
method adds a player listener
for a player, and the realize
method constructs portions of the Player
without acquiring the scarce and exclusive resources.
The getControl
method obtains the object that
implements the specified Control
interface, and the setSequence
method sets the tone sequence.
The following code shows the method for playing a specific sound:
public void playSound(int index) throws MediaException { if (supportMultiPlayer) { if (index >= 0 && index < players.size()) { Player player = (Player) players.elementAt(index); startPlayer(player); } } else { // use old player if already exists (has been previously played) if (index == realizedSoundIndex) { Player player = (Player) players.elementAt(0); startPlayer(player); return; } // otherwise close old player and create a new one. discardAll(); players.removeAllElements(); try { Object obj = medias.elementAt(index); Player player = createPlayer(obj); players.addElement(player); updateStopTime(); updateVolumeLevel(); realizedSoundIndex = index; startPlayer(player); } catch (IOException ioe) { midlet.alertError("IOException: " + ioe.getMessage()); } } } private void startPlayer(Player player) { try { if (player != null) { if (player.getState() == Player.UNREALIZED) { player.prefetch(); player.realize(); } if (player.getState() != Player.CLOSED) { Thread.sleep(latency); player.start(); } } Thread.sleep(latency); } catch (InterruptedException e) { } catch (MediaException e) { discardPlayer(player); midlet.alertError("MediaException: " + e.getMessage()); } }
The getState
method fetches the
current state of the specified Player
.
The following code shows the methods for closing a specific player or all players:
public void discardPlayer(Player player) { if (player != null) { player.close(); } } public void discardAll() { for (int i = 0; i < players.size(); i++) { Player player = (Player) players.elementAt(i); discardPlayer(player); } }
The following code shows the method for setting the volume level to the players:
private void updateVolumeLevel() { int size = players.size(); for (int i = 0; i < size; i++) { // Set the same volume level for all players Player player = (Player) players.elementAt(i); VolumeControl control = (VolumeControl) player.getControl("VolumeControl"); actualVolume = (int) (((float) globalVolume / 100) * (float) midletVolume); control.setLevel(midletVolume); } }
The setLevel
method sets the volume using a linear
point scale with values between 0 and 100.
The following code shows the method for setting the current stop time to the players:
private void updateStopTime() { int size = players.size(); for (int i = 0; i < size; i++) { // Set the same stop time for all players Player player = (Player) players.elementAt(i); StopTimeControl control = (StopTimeControl) player.getControl("StopTimeControl"); control.setStopTime(stopTime); } }
The StopTimeControl
class allows
the specifying of a preset stop time for a Player
. The setStopTime
method sets the media time at
which you want the Player
to stop.
A separate DRMPlayer
object handles the playing of DRM-protected files. DRM-protected
files can only be played using a direct locator string to a file.
It is not possible to play DRM-protected files packaged inside the
JAR file. For more information, see section Playing DRM-protected media.
The following code shows the method for playing DRM-protected files:
public void playDRMprotected(String file, String type) { if (file == null) { midlet.alertError("No file specified for type " + type); } else { try { player = Manager.createPlayer(file); player.addPlayerListener(this); player.realize(); player.start(); list.addCommand(stopCommand); } catch (IllegalArgumentException iae) { discardPlayer(); midlet.alertError("IllegalArgumentException: " + iae.getMessage() + " file: " + file); } catch (IOException ioe) { discardPlayer(); midlet.alertError("IOException: " + ioe.getMessage() + " file: " + file); } catch (MediaException me) { discardPlayer(); midlet.alertError("MediaException: " + me.getMessage() + " file: " + file); } catch (SecurityException se) { discardPlayer(); midlet.alertError("SecurityException: " + se.getMessage() + " file: " + file); } } }
The following code shows the methods for stopping, and initializing and starting the player:
void doStop() { if (player != null) { try { player.stop(); } catch (MediaException e) { e.printStackTrace(); } } } // ... void play() { try { if (!initDone || player == null) { initPlayer(); } int state = player.getState(); if (state == Player.CLOSED) { player.prefetch(); } else if (state == Player.UNREALIZED) { player.realize(); } else if (state == Player.REALIZED) { player.prefetch(); } player.start(); } catch (MediaException me) { discardPlayer(); midlet.alertError("MediaException: " + me.getMessage()); } catch (SecurityException se) { discardPlayer(); midlet.alertError("SecurityException: " + se.getMessage()); } catch (Exception e) { discardPlayer(); midlet.alertError("Exception: " + e.getMessage()); } }
The following code shows the method for initializing the video player:
void initPlayer() { try { initDone = false; if (videoFile == null) { midlet.alertError("No video file specified"); return; } boolean fromHttp = videoFile.startsWith("http://"); InputStream is = fromHttp ? urlToStream(videoFile) : getClass().getResourceAsStream(videoFile); player = Manager.createPlayer(is, "video/3gpp"); player.addPlayerListener(this); player.prefetch(); player.realize(); // get the video control and attach it to our canvas VideoControl videoControl = (VideoControl) (player.getControl("VideoControl")); if (videoControl == null) { midlet.alertError("VideoControl not supported"); } else { videoControl.initDisplayMode(VideoControl.USE_DIRECT_VIDEO, this); videoControl.setVisible(true); } initDone = true; } catch (IOException ioe) { discardPlayer(); midlet.alertError("IOException: " + ioe.getMessage()); } catch (MediaException me) { discardPlayer(); midlet.alertError("MediaException: " + me.getMessage()); } catch (SecurityException se) { discardPlayer(); midlet.alertError("SecurityException: " + se.getMessage()); } catch (Exception ex) { discardPlayer(); midlet.alertError("Exception: " + ex.getMessage()); } }
The VideoControl
class controls
the display of video. A Player
which supports the
playback of video must provide a VideoControl
through
its getControl
and getControls
methods. The initDisplayMode
method initializes the mode
on how the video is displayed.
The SupportForm
class shows
supported media types:
private void init() { String apiVersion = System.getProperty("microedition.media.version"); append("MM API version:" + apiVersion + "\n"); append("Mixing supported: " + System.getProperty("supports.mixing") + "\n"); append("Audio capture supported: " + System.getProperty("supports.audio.capture") + "\n"); append("Video capture supported: " + System.getProperty("supports.video.capture") + "\n"); append("Recording supported: " + System.getProperty("supports.recording") + "\n"); append("Supported audio encodings: " + System.getProperty("audio.encodings") + "\n"); append("Supported video encodings: " + System.getProperty("video.encodings") + "\n"); append("Supported video snaphot encodings: " + System.getProperty("video.snapshot.encodings") + "\n"); append("\n"); String streamable = System.getProperty("streamable.contents"); if (streamable == null) { append("Streaming: not supported.\n"); } else { append("Streamable contents: " + streamable); String[] rtp = Manager.getSupportedContentTypes("rtp"); if (rtp != null && rtp.length > 0) { append("RTP protocol supported."); } String rtsp[] = Manager.getSupportedContentTypes("rtsp"); if (rtsp != null && rtsp.length > 0) { append("RTSP protocol supported."); } } String[] contentTypes = Manager.getSupportedContentTypes(null); if (contentTypes != null) { append("\n\nAll supported content types:\n"); for (int i = 0; i < contentTypes.length; i++) { append(contentTypes[i] + "\n"); } } }