This section provides the source code for the Media Sampler. For the complete Eclipse project ZIP file , see Forum Nokia.
The example includes the following classes:
package com.nokia.example.mmapi.mediasampler; import javax.microedition.midlet.*; import javax.microedition.lcdui.*; import com.nokia.example.mmapi.mediasampler.data.MediaFactory; import com.nokia.example.mmapi.mediasampler.viewer.MediaList; /** * MMAPI example MIDlet class. */ public class MediaSamplerMIDlet extends MIDlet { private final MediaList list; public MediaSamplerMIDlet() { MediaFactory.setMidlet(this); list = new MediaList(this); } /** * Overriden MIDlet method */ public void startApp() { Displayable current = Display.getDisplay(this).getCurrent(); if (current == null) { // first call Display.getDisplay(this).setCurrent(list); } else { Display.getDisplay(this).setCurrent(current); } } /** * Overriden MIDlet method */ public void pauseApp() { } /** * Overriden MIDlet method. */ public void destroyApp(boolean unconditional) { list.releaseResources(); } /** * Exits the MIDlet. Called when exit command is selected from the * MediaList. */ public void listExit() { exitRequested(); } /** * Exits the MIDlet. */ private void exitRequested() { destroyApp(false); notifyDestroyed(); } /** * Displays an error message in Alert. * * @param message * String as message to display. */ public void alertError(String message) { Alert alert = new Alert("Error", message, null, AlertType.ERROR); Display display = Display.getDisplay(this); Displayable current = display.getCurrent(); if (!(current instanceof Alert)) { // This next call can't be done when current is an Alert display.setCurrent(alert, current); } } }
package com.nokia.example.mmapi.mediasampler.data; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.IOException; import java.io.InputStream; import javax.microedition.io.Connector; import javax.microedition.io.HttpConnection; /** * Datatype for the Medias. */ public class Media { private String file; private String type; private int location; public static final int LOCATION_JAR = 0; public static final int LOCATION_HTTP = 1; public static final int LOCATION_FILE = 3; public Media(String file, String type, int location) { this.file = file; this.type = type; this.location = location; } /** * Return location type of this media. * * @return int as type of this media location. Type value is one of the * constants LOCATION_JAR, LOCATION_HTTP or LOCATION_FILE. */ public int getLocation() { return location; } /** * Return file location of this Media. * * @return String as url or path to media. */ public String getFile() { return file; } /** * Returns mime type of this media. * * @return String as mime type */ public String getType() { return type; } /** * Returns InputStream to the media data. * * @return InputStream * @throws IOException */ 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!"); } /** * Reads the content from the specified HTTP URL and returns InputStream * where the contents are read. * * @return InputStream * @throws IOException */ 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; } }
package com.nokia.example.mmapi.mediasampler.data; import javax.microedition.media.control.ToneControl; import javax.microedition.midlet.MIDlet; /** * MediaFactory is a provides class for medias. */ public class MediaFactory { private static boolean soundInitDone = false; private static boolean videoInitDone = false; private static Media[] soundMedias; private static Media[] videoMedias; private static MIDlet mlet; public static Media getDefaultARM() { return getSoundMedias()[1]; } public static Media getDefaultMidi() { return getSoundMedias()[0]; } public static Media getDefaultXWav() { return getSoundMedias()[3]; } public static Media getDefaultWav() { return getSoundMedias()[2]; } public static Media getDRMMidi() { String drmFile = mlet.getAppProperty("DRM-Audio-Clip"); Media drmMedia = new Media(drmFile, "audio/midi", Media.LOCATION_FILE); return drmMedia; } public static Media getDefaultVideo() { return getVideoMedias()[0]; } public static void setMidlet(MIDlet midlet) { mlet = midlet; } public static Media[] getAllMedias() { return null; } public static Media[] getSoundMedias() { if (!soundInitDone) { String armFile = mlet.getAppProperty("AMR-Audio-Clip"); String midiFile = mlet.getAppProperty("MIDI-Audio-Clip"); String wavFile = mlet.getAppProperty("WAV-Audio-Clip"); Media m1 = new Media(midiFile, "audio/midi", Media.LOCATION_JAR); Media m2 = new Media(armFile, "audio/amr", Media.LOCATION_JAR); Media m3 = new Media(wavFile, "audio/wav", Media.LOCATION_JAR); Media m4 = new Media(wavFile, "audio/x-wav", Media.LOCATION_JAR); soundMedias = new Media[] { m1, m2, m3, m4 }; soundInitDone = true; } return soundMedias; } public static Media[] getVideoMedias() { if (!videoInitDone) { String videoFile = mlet.getAppProperty("Video-Clip"); Media m = new Media(videoFile, "video/3gpp", Media.LOCATION_JAR); videoMedias = new Media[] { m }; videoInitDone = true; } return videoMedias; } 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; } }
package com.nokia.example.mmapi.mediasampler.model; import java.io.IOException; import javax.microedition.lcdui.Command; import javax.microedition.lcdui.CommandListener; import javax.microedition.lcdui.Display; import javax.microedition.lcdui.Displayable; import javax.microedition.media.Manager; import javax.microedition.media.MediaException; import javax.microedition.media.Player; import javax.microedition.media.PlayerListener; import com.nokia.example.mmapi.mediasampler.MediaSamplerMIDlet; import com.nokia.example.mmapi.mediasampler.viewer.MediaList; /** * Player with DRM protected audio. */ public class DRMPlayer implements CommandListener, PlayerListener { private Player player; private MediaSamplerMIDlet midlet; private final Command stopCommand; private MediaList list; public DRMPlayer(MediaSamplerMIDlet midlet, MediaList list) { this.midlet = midlet; this.list = list; stopCommand = new Command("Stop", Command.ITEM, 2); } /** * Releases resources * */ public void releaseResources() { discardPlayer(); } public void commandAction(Command cmd, Displayable disp) { if (cmd == stopCommand) { discardPlayer(); } } public void playerUpdate(final Player p, final String event, final Object eventData) { // queue a call to updateEvent in the user interface event queue Display display = Display.getDisplay(midlet); display.callSerially(new Runnable() { public void run() { DRMPlayer.this.updateEvent(p, event, eventData); } }); } public void stop() { if (player != null) { player.close(); } } // Called in case of exception to make sure invalid players are closed private void discardPlayer() { if (player != null) { player.close(); player = null; } list.removeCommand(stopCommand); } private void updateEvent(Player p, String event, Object eventData) { if (event == END_OF_MEDIA) { discardPlayer(); } else if (event == CLOSED) { player = null; list.removeCommand(stopCommand); } } 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); } } } }
package com.nokia.example.mmapi.mediasampler.model; import java.io.IOException; import java.io.InputStream; import java.util.Vector; import javax.microedition.media.Manager; import javax.microedition.media.MediaException; import javax.microedition.media.Player; import javax.microedition.media.PlayerListener; import javax.microedition.media.control.StopTimeControl; import javax.microedition.media.control.ToneControl; import javax.microedition.media.control.VolumeControl; import com.nokia.example.mmapi.mediasampler.MediaSamplerMIDlet; import com.nokia.example.mmapi.mediasampler.data.Media; /** * PlayerPool enables multiple realized / prefetched players. */ public class PlayerPool implements PlayerListener { protected Vector players; protected Vector medias; protected MediaSamplerMIDlet midlet; protected int latency; boolean supportMultiPlayer = true; private int volumeLevel = 100; private long stopTime = StopTimeControl.RESET; private int realizedSoundIndex; public PlayerPool(MediaSamplerMIDlet midlet, int latency) { this.midlet = midlet; this.latency = latency; players = new Vector(); medias = new Vector(); } /** * PlayerListener interface's method. */ public void playerUpdate(Player player, String event, Object eventData) { } /** * Returns boolean indication is media mimetype supported by the Device. * * @param mimeType * String as media mime-type * @return boolean is supported */ 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; } /** * Add media to pool. * * @param media - * Media to add */ public void addMedia(Media media) throws MediaException { String mimeType = media.getType(); if (!isMediaSupported(mimeType)) { throw new MediaException("Type " + mimeType + " is not supported!"); } addSoundObject(media); } /** * Return true if device supports multiple simultaneous players. * * @return a boolean indication are multiple players supported. */ public boolean supportsMulplePlayers() { return supportMultiPlayer; } /** * Adds Tone Sequence to this * * @param sequence * @throws MediaException - * if tone sequence is not supported */ 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); } /** * Creates and initializes the Player * * @param sequence - * tone sequence data in byte array * @return realized tone sequence Player * @throws MediaException * thrown by the system while creating the player * @throws IOException * thrown by the system while creating the 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; } /** * Creates and initializes the Player. * * @param media - * Media datatype that represents the data * @return realized tone sequence Player * @throws MediaException * occured while creating the player * @throws IOException * occured while creating the player */ private Player createPlayer(Object media) throws MediaException, IOException { if (media instanceof byte[]) { return createTonePlayer((byte[]) media); } return createPlayer((Media) media); } /** * Creates and initializes the Player. * * @param media - * Media datatype that represents the data * @return realized tone sequence Player * @throws MediaException * occured while creating the player * @throws IOException * occured while creating the player */ 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; } /** * Closes the players and removes all references. */ public void releaseResources() { discardAll(); players.removeAllElements(); medias.removeAllElements(); } /** * Set the volume level of players. * * @param volume * int as volume level in range 0-100. */ public void setVolumeLevel(int volume) { volumeLevel = volume; updateVolumeLevel(); } /** * Set the stop time of players. * * @param time * long as stop time in millis */ public void setStopTime(long time) { this.stopTime = time; updateStopTime(); } /** * Plays the specified sound. * * @param index * int as sound index to play */ 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()); } } 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); } } /** * Set volume level to existing 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"); control.setLevel(volumeLevel); } } /** * Set current stop-time to existing 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); } } 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()); } } } }
package com.nokia.example.mmapi.mediasampler.viewer; import java.util.Vector; import javax.microedition.lcdui.Canvas; import javax.microedition.lcdui.Command; import javax.microedition.lcdui.CommandListener; import javax.microedition.lcdui.Display; import javax.microedition.lcdui.Displayable; import javax.microedition.lcdui.Font; import javax.microedition.lcdui.Graphics; import javax.microedition.media.MediaException; import com.nokia.example.mmapi.mediasampler.MediaSamplerMIDlet; import com.nokia.example.mmapi.mediasampler.data.Media; import com.nokia.example.mmapi.mediasampler.data.MediaFactory; import com.nokia.example.mmapi.mediasampler.model.PlayerPool; /** * Audio play canvas. Audio clip is played when a key is pressed. */ public class AudioCanvas extends Canvas implements CommandListener { private PlayerPool pool; private MediaSamplerMIDlet midlet; private Displayable returnScreen; protected String[] supportedMediaNames; protected String[] unsupportedMediaNames; protected int countOfPlayers = 0; protected int volume = 100; private boolean initDone; private boolean infoMode; private Command infoCommand = new Command("Info", Command.SCREEN, 1); private Command backCommand = new Command("Back", Command.BACK, 1); public AudioCanvas(MediaSamplerMIDlet midlet, Displayable returnScreen, int latency) { this.midlet = midlet; this.returnScreen = returnScreen; pool = new PlayerPool(midlet, latency); initSounds(); // Init volume level of Players in pool pool.setVolumeLevel(volume); addCommand(backCommand); addCommand(infoCommand); setCommandListener(this); } /** * Release loaded resources */ public void releaseResources() { pool.releaseResources(); } /** * Implemented CommandListener method. */ public void commandAction(Command cmd, Displayable d) { if (cmd == backCommand) { if (infoMode) { infoMode = false; addCommand(infoCommand); repaint(); } else { Display.getDisplay(midlet).setCurrent(returnScreen); } } else if (cmd == infoCommand) { infoMode = true; removeCommand(infoCommand); repaint(); } } public void keyPressed(int key) { int keyCode = key - KEY_NUM0; int gameAction = getGameAction(key); // Check is the selected audio available for playing. if (keyCode > 0 && keyCode <= countOfPlayers) { try { pool.playSound(keyCode - 1); } catch (MediaException e) { // Swallow the exception. } } else if (gameAction == UP) { increaseVolume(); } else if (gameAction == DOWN) { decreaseVolume(); } } /** * Paint the canvas. */ protected void paint(Graphics g) { int x = 0; int y = 0; int w = getWidth(); int h = getHeight(); g.setColor(0xFFFFFF); g.fillRect(x, y, w, h); Font fontPlain = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_SMALL); Font fontBold = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_BOLD, Font.SIZE_SMALL); g.setColor(0x000000); if (infoMode) { boolean multiSupport = pool.supportsMulplePlayers(); boolean mixSupport = "true".equals(System .getProperty("supports.mixing")); g.setFont(fontBold); y = paintTextRow(g, "Supports multiple players:", x, y); g.setFont(fontPlain); y = paintTextRow(g, "" + multiSupport, x, y); g.setFont(fontBold); y = paintTextRow(g, "Supports audio mixing:", x, y); g.setFont(fontPlain); y = paintTextRow(g, "" + mixSupport, x, y); if (unsupportedMediaNames.length > 0) { g.setFont(fontBold); g.setColor(0x000000); y = paintTextRow(g, "Unsupported sounds:", x, y); g.setFont(fontPlain); for (int i = 0; i < unsupportedMediaNames.length; i++) { String str = unsupportedMediaNames[i]; String strToPaint = str; y = paintTextRow(g, strToPaint, x, y); } } } else { g.setFont(fontBold); y = paintTextRow(g, "Sound key mapping:", x, y); g.setFont(fontPlain); for (int i = 0; i < supportedMediaNames.length; i++) { String str = supportedMediaNames[i]; String strToPaint = (i + 1) + " = " + str; y = paintTextRow(g, strToPaint, x, y); } y = paintTextRow(g, "Volume level: " + volume, x, y); } } /** * Renders a text row to Canvas. */ private int paintTextRow(Graphics g, String text, int x, int y) { int w = getWidth(); Font font = g.getFont(); for (int j = 0; j < text.length(); j++) { char c = text.charAt(j); int cw = font.charWidth(c); if (x + cw > w) { x = 0; y += font.getHeight(); } g.drawChar(c, x, y, Graphics.TOP | Graphics.LEFT); x += cw; } y += font.getHeight(); return y; } private void increaseVolume() { volume += 10; if (volume > 100) { volume = 100; } pool.setVolumeLevel(volume); repaint(); } private void decreaseVolume() { volume -= 10; if (volume < 0) { volume = 0; } pool.setVolumeLevel(volume); repaint(); } /** * Loads the medias available on this canvas. Loaded sounds are passed to * PlayerPool class which creates players and initializes player states. */ protected void initSounds() { if (!initDone) { countOfPlayers = 0; Vector supportedMedias = new Vector(); Vector unsupportedMedias = new Vector(); // Sound media clips Media[] medias = MediaFactory.getSoundMedias(); for (int i = 0; i < medias.length; i++) { Media media = medias[i]; String mediaName = null; try { mediaName = media.getFile() + " [" + media.getType() + "]"; pool.addMedia(media); supportedMedias.addElement(mediaName); countOfPlayers++; } catch (MediaException e) { System.out.println("unsupported media: " + media.getType()); unsupportedMedias.addElement(mediaName); } } // Tone sequences String mediaName = null; try { mediaName = "Tone sequence"; pool.addToneSequence(MediaFactory.getToneSequence()); supportedMedias.addElement(mediaName); countOfPlayers++; } catch (MediaException e) { System.out.println("Unsupported type: Tone sequence"); e.printStackTrace(); unsupportedMedias.addElement(mediaName); } // Stores results of success and failed Players to String array supportedMediaNames = new String[supportedMedias.size()]; supportedMedias.copyInto(supportedMediaNames); unsupportedMediaNames = new String[unsupportedMedias.size()]; unsupportedMedias.copyInto(unsupportedMediaNames); initDone = true; } } }
package com.nokia.example.mmapi.mediasampler.viewer; import javax.microedition.lcdui.*; import com.nokia.example.mmapi.mediasampler.MediaSamplerMIDlet; import com.nokia.example.mmapi.mediasampler.data.Media; import com.nokia.example.mmapi.mediasampler.data.MediaFactory; import com.nokia.example.mmapi.mediasampler.model.DRMPlayer; /** * Media list is the main view in the MIDlet. From this view the user may swich * to other views. */ public class MediaList extends List implements CommandListener { private final MediaSamplerMIDlet midlet; private final VideoSourceSelector sourceSelector; private AudioCanvas audioCanvas; private SupportForm form; private final Command exitCommand; public MediaList(MediaSamplerMIDlet midlet) { super("Media Sampler", IMPLICIT); this.midlet = midlet; sourceSelector = new VideoSourceSelector(midlet, this); append("Play audio", null); append("Play video", null); append("DRM MIDI", null); append("Check MM API support", null); exitCommand = new Command("Exit", Command.EXIT, 1); addCommand(exitCommand); setCommandListener(this); } /** * Release all resources loaded by sub components. */ public void releaseResources() { if (audioCanvas != null) { audioCanvas.releaseResources(); } } /** * Implemented CommandListener method. * * Sets the selected Example visible */ public void commandAction(Command cmd, Displayable disp) { if (cmd == List.SELECT_COMMAND) { int index = getSelectedIndex(); if (index != -1) // -1 means nothing selected { String selected = getString(index); if (selected.equals("Play video")) { Display.getDisplay(midlet).setCurrent(sourceSelector); } else if (selected.equals("DRM MIDI")) { Media media = MediaFactory.getDRMMidi(); DRMPlayer player = new DRMPlayer(midlet, this); player.playDRMprotected(media.getFile(), media.getType()); } else if (selected.equals("Play audio")) { if (audioCanvas == null) { audioCanvas = new AudioCanvas(midlet, this, 0); } Display.getDisplay(midlet).setCurrent(audioCanvas); } else if (selected.equals("Check MM API support")) { if (form == null) { form = new SupportForm(midlet, this); } Display.getDisplay(midlet).setCurrent(form); } } } else if (cmd == exitCommand) { midlet.listExit(); } } }
package com.nokia.example.mmapi.mediasampler.viewer; import javax.microedition.lcdui.Command; import javax.microedition.lcdui.CommandListener; import javax.microedition.lcdui.Display; import javax.microedition.lcdui.Displayable; import javax.microedition.lcdui.Form; import javax.microedition.media.Manager; import com.nokia.example.mmapi.mediasampler.MediaSamplerMIDlet; /** * View that outputs MM API's System properties to a Form. */ public class SupportForm extends Form implements CommandListener { private MediaSamplerMIDlet midlet; private Displayable medialist; private Command backCmd = new Command("Back", Command.STOP, 1); public SupportForm(MediaSamplerMIDlet midlet, Displayable medialist) { super("MM API support check"); this.midlet = midlet; this.medialist = medialist; addCommand(backCmd); setCommandListener(this); init(); } 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"); } } } public void commandAction(Command cmd, Displayable d) { Display.getDisplay(midlet).setCurrent(medialist); } }
package com.nokia.example.mmapi.mediasampler.viewer; import java.io.*; import javax.microedition.io.Connector; import javax.microedition.io.HttpConnection; import javax.microedition.lcdui.*; import javax.microedition.media.*; import javax.microedition.media.control.*; import com.nokia.example.mmapi.mediasampler.MediaSamplerMIDlet; /** * VideoCanvas renders video on Canvas. */ class VideoCanvas extends Canvas implements CommandListener, PlayerListener { private PlayerController controller; private MediaSamplerMIDlet midlet; private Displayable returnScreen; private String videoFile; private Command stopCommand; private Command replayCommand; private Command backCommand; private Player player; private boolean initDone; private boolean playPending = false; /** * Constructor. * * @param midlet * MediaSamplerMIDlet * @param returnScreen * Displayable to set visible when returned from this Canvas * @param videoFile * String as path of the source viudeo file. */ VideoCanvas(MediaSamplerMIDlet midlet, Displayable returnScreen, String videoFile) { this.midlet = midlet; this.returnScreen = returnScreen; this.videoFile = videoFile; controller = new PlayerController(); replayCommand = new Command("Replay", Command.SCREEN, 1); stopCommand = new Command("Stop", Command.SCREEN, 2); backCommand = new Command("Back", Command.BACK, 1); addCommand(backCommand); setCommandListener(this); } /** * Set play status to "pending". */ void prepareToPlay() { controller.start(); playPending = true; } /** * Play video only when we're displayed. Use playPending flag to avoid * restarting if a system screen is visiable. */ public void showNotify() { if (playPending) { playPending = false; controller.playVideo(); } } /** * Renders the Canvas. */ public void paint(Graphics g) { g.setColor(0x00FFFF00); // yellow g.fillRect(0, 0, getWidth(), getHeight()); } /** * Implemented CommandListener method. Indicates that a command event has * occurred on Displayable d. */ public void commandAction(Command c, Displayable d) { if (c == stopCommand) { controller.stopVideo(); } else if (c == replayCommand) { controller.playVideo(); } else if (c == backCommand) { discardPlayer(); } } /** * Overriden Canvas method. */ public void keyPressed(int keyCode) { if (getGameAction(keyCode) == FIRE) { int state = player.getState(); if (state == Player.STARTED) { controller.stopVideo(); } else { controller.playVideo(); } } } /** * Reads the content from the specified HTTP URL and returns InputStream * where the contents are read. * * @return InputStream * @throws IOException */ 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(); connection.close(); // Fill InputStream to return with content read from the URL. ByteArrayInputStream byteIn = new ByteArrayInputStream(byteout .toByteArray()); return byteIn; } /** * Stops the Player. */ void doStop() { if (player != null) { try { player.stop(); } catch (MediaException e) { e.printStackTrace(); } } } /** * Initializes and starts the Player. */ void doPlay() { 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()); } } /** * Initializes the video player. * * Player is initialized only once to save the memory resorces and to * increase performance. */ 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()); } } /** * Called in case of exception to make sure invalid players are closed */ void discardPlayer() { if (player != null) { controller.setStopped(); player.close(); player = null; Display.getDisplay(midlet).setCurrent(returnScreen); } } /** * Implemented javax.microedition.media.PlayerListener method. */ public void playerUpdate(final Player p, final String event, final Object eventData) { // queue a call to updateEvent in the user interface event queue Display display = Display.getDisplay(midlet); display.callSerially(new Runnable() { public void run() { VideoCanvas.this.updateEvent(p, event, eventData); } }); } /** * Handles playerUpdate events of the Player. * * @param p * @param event * @param eventData */ void updateEvent(Player p, String event, Object eventData) { if (event == END_OF_MEDIA) { addCommand(replayCommand); removeCommand(stopCommand); } else if (event == CLOSED) { addCommand(replayCommand); removeCommand(stopCommand); } else if (event == STARTED) { removeCommand(replayCommand); addCommand(stopCommand); } else if (event.equals(ERROR)) { } } /** * PlayerController calls the play and stop methods of the Player. The * purpose of this class is only to isolate Player method calls from the * event threads (such commandAction(...)) */ public class PlayerController extends Thread { private boolean running; // Lock object ofthis Thread private Object controllLock = new Object(); public PlayerController() { } // Activates the Player public void playVideo() { synchronized (controllLock) { controllLock.notify(); } } // Deactivates the player public void stopVideo() { synchronized (controllLock) { doStop(); } } // Terminates this thread public void setStopped() { running = false; synchronized (controllLock) { controllLock.notify(); } } public void run() { VideoCanvas.this.doPlay(); running = true; while (running) { try { synchronized (controllLock) { // Set this thread to wait for playVideo() method call. controllLock.wait(); if (!running) // Leave if controller is stopped. { break; } VideoCanvas.this.doPlay(); } } catch (Exception e) { e.printStackTrace(); } } } } }
package com.nokia.example.mmapi.mediasampler.viewer; import javax.microedition.lcdui.Command; import javax.microedition.lcdui.CommandListener; import javax.microedition.lcdui.Display; import javax.microedition.lcdui.Displayable; import javax.microedition.lcdui.Form; import javax.microedition.lcdui.List; import javax.microedition.lcdui.TextField; import com.nokia.example.mmapi.mediasampler.MediaSamplerMIDlet; import com.nokia.example.mmapi.mediasampler.data.MediaFactory; /** * List that allow user to select Video source. */ public class VideoSourceSelector extends List implements CommandListener { private MediaSamplerMIDlet midlet; private List returnList; private HTTPUrlForm urlForm; private Command backCommand = new Command("Back", Command.BACK, 1); public VideoSourceSelector(MediaSamplerMIDlet midlet, MediaList list) { super("Select Video Source", List.IMPLICIT); this.midlet = midlet; this.returnList = list; urlForm = new HTTPUrlForm(); append("From http", null); append("From jar", null); addCommand(backCommand); setCommandListener(this); } public void commandAction(Command cmd, Displayable d) { if (cmd == SELECT_COMMAND) { int selection = getSelectedIndex(); if (selection == 0) // URL source selected { Display.getDisplay(midlet).setCurrent(urlForm); } else if (selection == 1) // JAR source selected { // File name returned by the MediaFactory refers to the // "Video-Clip" application property... String videoFile = MediaFactory.getDefaultVideo().getFile(); commitSelection(videoFile); } } else if (cmd == backCommand) { Display.getDisplay(midlet).setCurrent(returnList); } } /** * Initializes and set visible the video canvas with the selected video * source. * * @param input * String as video http url or file path. */ private void commitSelection(String url) { try { VideoCanvas canvas = new VideoCanvas(midlet, returnList, url); canvas.prepareToPlay(); Display.getDisplay(midlet).setCurrent(canvas); } catch (Exception e) { midlet.alertError("Cannot open connection: " + e.getMessage()); } } /** * Form for the video URL input. */ public class HTTPUrlForm extends Form implements CommandListener { TextField tf = new TextField("URL", "http://", 100, TextField.URL); Command cmdOK = new Command("OK", Command.OK, 1); Command cmdBack = new Command("Back", Command.BACK, 1); public HTTPUrlForm() { super("HTTP Address"); String defaultURL = VideoSourceSelector.this.midlet .getAppProperty("Video-URL"); if (defaultURL != null && defaultURL.length() > 0) { tf.setString(defaultURL); } append(tf); addCommand(cmdOK); addCommand(cmdBack); setCommandListener(this); } public void commandAction(Command cmd, Displayable d) { if (cmd == cmdOK) { String url = tf.getString(); commitSelection(url); } else { Display.getDisplay(midlet).setCurrent(VideoSourceSelector.this); } } } }