/*
* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores
* CA 94065 USA or visit www.oracle.com if you need additional information or
* have any questions.
*/
package com.sun.lwuit.impl.midp;
import com.sun.lwuit.Component;
import com.sun.lwuit.Display;
import com.sun.lwuit.Form;
import com.sun.lwuit.PeerComponent;
import com.sun.lwuit.TextArea;
import com.sun.lwuit.VideoComponent;
import com.sun.lwuit.events.ActionEvent;
import com.sun.lwuit.geom.Dimension;
import com.sun.lwuit.impl.LWUITImplementation;
import com.sun.lwuit.plaf.UIManager;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Hashtable;
import java.util.Vector;
import javax.microedition.io.ConnectionNotFoundException;
import javax.microedition.lcdui.AlertType;
import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.TextBox;
import javax.microedition.lcdui.game.GameCanvas;
import javax.microedition.lcdui.game.Sprite;
import javax.microedition.media.Manager;
import javax.microedition.media.MediaException;
import javax.microedition.media.Player;
import javax.microedition.media.PlayerListener;
import javax.microedition.midlet.MIDlet;
import javax.microedition.media.control.VideoControl;
import javax.microedition.media.control.VolumeControl;
import javax.microedition.media.protocol.DataSource;
/**
* An implementation of LWUIT based on game canvas, this is the default implementation
* class for LWUIT which most customizers should extend to enhance.
*
* @author Shai Almog
*/
public class GameCanvasImplementation extends LWUITImplementation {
private static boolean NOKIA = false;
private boolean minimized;
private MIDlet mid;
private Object currentlyPlayingAudio;
/**
* On some devices getKeyCode returns numeric values for game actions,
* this breaks the code since we filter these values. We pick unused
* negative values for game keys and assign them to game keys for getKeyCode.
*/
private static int[] portableKeyCodes;
private static int[] portableKeyCodeValues;
private int alpha = 255;
private int[] rgbArr;
private Canvas canvas;
private class C extends GameCanvas implements CommandListener, Runnable {
private boolean done;
private Command[] currentCommands;
class MIDP2LWUITCommand extends Command {
com.sun.lwuit.Command internal;
public MIDP2LWUITCommand(com.sun.lwuit.Command c, int offset) {
super(c.getCommandName(), Command.SCREEN, offset);
internal = c;
}
public MIDP2LWUITCommand(com.sun.lwuit.Command c, int type, int offset) {
super(c.getCommandName(), type, offset);
internal = c;
}
}
public void setCommands(Vector v) {
if(currentCommands != null) {
for(int iter = 0 ; iter < currentCommands.length ; iter++) {
removeCommand(currentCommands[iter]);
}
}
setCommandListener(this);
currentCommands = new Command[v.size()];
com.sun.lwuit.Command backCommand = null;
if(Display.getInstance().getCurrent() != null) {
backCommand = Display.getInstance().getCurrent().getBackCommand();
}
for(int iter = 0 ; iter < currentCommands.length ; iter++) {
com.sun.lwuit.Command current = (com.sun.lwuit.Command)v.elementAt(iter);
if(current == backCommand) {
currentCommands[iter] = new MIDP2LWUITCommand(current, Command.BACK, iter + 1);
} else {
if(iter == 0) {
currentCommands[iter] = new MIDP2LWUITCommand(current, Command.OK, iter + 1);
} else {
currentCommands[iter] = new MIDP2LWUITCommand(current, iter + 1);
}
}
addCommand(currentCommands[iter]);
}
}
public void run() {
while (!done) {
synchronized (getDisplayLock()) {
try {
getDisplayLock().wait(50);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
}
public void setDone(boolean done) {
this.done = done;
synchronized (getDisplayLock()) {
getDisplayLock().notify();
}
}
public void commandAction(Command c, Displayable d) {
if (d == currentTextBox) {
display.setCurrent(canvas);
if (c == CONFIRM_COMMAND) {
// confirm
String text = currentTextBox.getString();
getCurrentForm().setVisible(true);
Display.getInstance().onEditingComplete(currentTextComponent, text);
}
currentTextBox = null;
((C)canvas).setDone(true);
} else {
if(c instanceof MIDP2LWUITCommand) {
final com.sun.lwuit.Command cmd = ((MIDP2LWUITCommand)c).internal;
Display.getInstance().callSerially(new Runnable() {
public void run() {
Display.getInstance().getCurrent().dispatchCommand(cmd, new ActionEvent(cmd));
}
});
}
}
}
private javax.microedition.lcdui.Graphics gfx;
C() {
super(false);
}
public javax.microedition.lcdui.Graphics getGraphics() {
if (gfx == null) {
gfx = super.getGraphics();
}
return gfx;
}
protected void keyPressed(final int keyCode) {
GameCanvasImplementation.this.keyPressed(keyCode);
}
protected void keyReleased(final int keyCode) {
GameCanvasImplementation.this.keyReleased(keyCode);
}
protected void pointerDragged(final int x, final int y) {
GameCanvasImplementation.this.pointerDragged(x, y);
}
protected void pointerPressed(final int x, final int y) {
//solves an emulator bug(no impact on real devices)
Display.getInstance().setTouchScreenDevice(true);
GameCanvasImplementation.this.pointerPressed(x, y);
}
protected void pointerReleased(final int x, final int y) {
GameCanvasImplementation.this.pointerReleased(x, y);
}
protected void sizeChanged(int w, int h) {
GameCanvasImplementation.this.sizeChanged(w, h);
}
protected void hideNotify() {
GameCanvasImplementation.this.hideNotify();
}
protected void showNotify() {
GameCanvasImplementation.this.showNotify();
}
}
private static final AlertType[] TYPES = new AlertType[]{
AlertType.ALARM, AlertType.CONFIRMATION, AlertType.ERROR,
AlertType.INFO, AlertType.WARNING
};
/**
* The command used for accepting a text field change
*/
static Command CONFIRM_COMMAND;
/**
* The end time of the last call to vibrate
*/
private long lastVibrate;
/**
* The command used for canceling a text field change
*/
static Command CANCEL_COMMAND;
/**
* The currently edited text box used to input into text field, this is a MIDP implementation
* detail.
*/
TextBox currentTextBox;
/**
* The currently edited text component that will be updated after the dismissal
* of the text box
*/
Component currentTextComponent;
private boolean flushGraphicsBug;
static javax.microedition.lcdui.Display display;
/**
* This member holds the left soft key value
*/
static int[] leftSK = new int[]{-6};
/**
* This member holds the right soft key value
*/
static int[] rightSK = new int[]{-7};
/**
* This member holds the back command key value
*/
static int backSK = -11;
/**
* This member holds the clear command key value
*/
static int clearSK = -8;
static int backspaceSK = -8;
/**
* This flag indicates if the drawRGB method is able to draw negative x and y
* In drawRGB method, some devices such as BlackBerry throw exceptions if you
* try to give negative values to drawRGB method.
*/
private static boolean drawNegativeOffsetsInRGB = true;
/**
* Allows a subclass to create its own canvas implemention
*
* @return the canvas implementation
*/
protected Canvas createCanvas() {
return new C();
}
public GameCanvasImplementation() {
// code should be in the init to allow assignment into implementation first
}
/**
* @inheritDoc
*/
public int getKeyboardType() {
// See http://wiki.forum.nokia.com/index.php/How_to_utilize_different_keyboards_in_Java_ME for details on
// Nokia keyboard types
String keyboardType = System.getProperty("com.nokia.keyboard.type");
if(keyboardType != null) {
if("None".equalsIgnoreCase(keyboardType)) {
if(isTouchDevice()) {
return Display.KEYBOARD_TYPE_VIRTUAL;
}
// annoying behavior of some phones where none is returned for numeric
// see http://forums.java.net/jive/thread.jspa?messageID=400135
return Display.KEYBOARD_TYPE_NUMERIC;
}
if("PhoneKeypad".equalsIgnoreCase(keyboardType)) {
return Display.KEYBOARD_TYPE_NUMERIC;
}
if("HalfKeyboard".equalsIgnoreCase(keyboardType)) {
return Display.KEYBOARD_TYPE_HALF_QWERTY;
}
if("FullKeyboard".equalsIgnoreCase(keyboardType)) {
return Display.KEYBOARD_TYPE_QWERTY;
}
if("LimitedKeyboard4x10".equalsIgnoreCase(keyboardType)) {
return Display.KEYBOARD_TYPE_QWERTY;
}
if("LimitedKeyboard3x11".equalsIgnoreCase(keyboardType)) {
return Display.KEYBOARD_TYPE_QWERTY;
}
}
return super.getKeyboardType();
}
/**
* @inheritDoc
*/
public void init(Object m) {
canvas = createCanvas();
canvas.setTitle(null);
canvas.setFullScreenMode(!com.sun.lwuit.Display.getInstance().isNativeCommands());
// disable the flashGraphics bug on Nokia phones
String platform = System.getProperty("microedition.platform");
if (platform != null && platform.toUpperCase().indexOf("NOKIA") >= 0) {
flushGraphicsBug = false;
NOKIA = true;
// Symbian devices should yield a bit to let the paint thread complete its work
// problem is we can't differentiate S40 from S60...
Display.getInstance().setTransitionYield(1);
} else {
flushGraphicsBug = true;
Display.getInstance().setTransitionYield(-1);
}
mid = (MIDlet)m;
display = javax.microedition.lcdui.Display.getDisplay(mid);
setSoftKeyCodes(mid);
}
private void setSoftKeyCodes(MIDlet m) {
// initialy set known key codes
setKnownSoftKeyCodes();
try {
// if the back key is assigned to a game action by mistake then
// workaround it implicitly
int game = getGameAction(backSK);
if (game == GameCanvas.UP || game == GameCanvas.DOWN || game == GameCanvas.RIGHT ||
game == GameCanvas.LEFT || game == GameCanvas.FIRE) {
backSK = -50000;
}
} catch (Exception ok) {
}
try {
// if the clear key is assigned to a game action by mistake then
// workaround it implicitly
int game = getGameAction(clearSK);
if (game == GameCanvas.UP || game == GameCanvas.DOWN || game == GameCanvas.RIGHT ||
game == GameCanvas.LEFT || game == GameCanvas.FIRE) {
clearSK = -50000;
}
game = getGameAction(backspaceSK);
if (game == GameCanvas.UP || game == GameCanvas.DOWN || game == GameCanvas.RIGHT ||
game == GameCanvas.LEFT || game == GameCanvas.FIRE) {
backspaceSK = -50000;
}
} catch (Exception ok) {
}
// Then Check JAD file for overide specific key mapping
String tmpSoftKey = m.getAppProperty("SoftKey-Right");
if (tmpSoftKey != null && !"".equals(tmpSoftKey)) {
rightSK[0] = Integer.valueOf(tmpSoftKey).intValue();
}
tmpSoftKey = m.getAppProperty("SoftKey-Right2");
if (tmpSoftKey != null && !"".equals(tmpSoftKey)) {
rightSK = new int[]{rightSK[0], Integer.valueOf(tmpSoftKey).intValue()};
}
tmpSoftKey = m.getAppProperty("SoftKey-Left");
if (tmpSoftKey != null && !"".equals(tmpSoftKey)) {
leftSK[0] = Integer.valueOf(tmpSoftKey).intValue();
}
tmpSoftKey = m.getAppProperty("SoftKey-Back");
if (tmpSoftKey != null && !"".equals(tmpSoftKey)) {
backSK = Integer.valueOf(tmpSoftKey).intValue();
}
tmpSoftKey = m.getAppProperty("SoftKey-Clear");
if (tmpSoftKey != null && !"".equals(tmpSoftKey)) {
clearSK = Integer.valueOf(tmpSoftKey).intValue();
}
tmpSoftKey = m.getAppProperty("SoftKey-Backspace");
if (tmpSoftKey != null && !"".equals(tmpSoftKey)) {
backspaceSK = Integer.valueOf(tmpSoftKey).intValue();
}
// Check Third Soft Button is supported
tmpSoftKey = m.getAppProperty("isThirdSoftButtonSupported");
if (tmpSoftKey != null && "true".equals(tmpSoftKey.toLowerCase().trim())) {
Display.getInstance().setThirdSoftButton(true);
}
}
private void setKnownSoftKeyCodes() {
try {
Class.forName("com.siemens.mp.game.Light");
leftSK[0] = -1;
rightSK[0] = -4;
clearSK = -12;
backspaceSK = -12;
return;
} catch (ClassNotFoundException _ex) {
}
try {
Class.forName("com.motorola.phonebook.PhoneBookRecord");
leftSK[0] = -21;
rightSK[0] = -22;
return;
//maybe Motorola A1000 has different keyCodes
//Left soft key: Key code -10,
//Right soft key: Key code -11,
} catch (ClassNotFoundException _ex) {
}
try {
Class.forName("com.nokia.mid.ui.FullCanvas");
leftSK[0] = -6;
rightSK[0] = -7;
clearSK = -8;
backspaceSK = -8;
// prevent this from breaking Sony Ericsson devices
String p = System.getProperty("microedition.platform");
if (p != null && p.toUpperCase().indexOf("NOKIA") >= 0) {
backspaceSK = 8;
}
return;
} catch (Throwable ex) {
}
try {
Class.forName("net.rim.device.api.system.Application");
//there are no soft keys on the Blackberry
//instead use the Q and P keys
leftSK[0] = 113;
//some BB devices use O as the most right key
rightSK = new int[]{112, 111};
clearSK = 8;
backspaceSK = 8;
return;
} catch (ClassNotFoundException ex) {
}
// detecting LG
try {
// iden device
Class.forName("com.mot.iden.util.Base64");
clearSK = -5000;
backspaceSK = -5000;
leftSK[0] = -20;
rightSK[0] = -21;
setFireValue(-23);
return;
} catch (Throwable ex) {
}
try {
Class.forName("mmpp.media.MediaPlayer");
clearSK = -204;
backspaceSK = -204;
} catch (ClassNotFoundException ex) {
}
try {
if (canvas.getKeyName(-6).toUpperCase().indexOf("SOFT") >= 0) {
leftSK[0] = -6;
rightSK[0] = -7;
return;
}
if (canvas.getKeyName(21).toUpperCase().indexOf("SOFT") >= 0) {
leftSK[0] = 21;
rightSK[0] = 22;
return;
}
} catch (Exception ex) {
}
boolean leftInit = false;
boolean rightInit = false;
for (int i = -127; i < 127; i++) {
if (leftInit && rightInit) { //I have added this if to avoid unnecessary loops
return; //but the main reason is that sometimes after the correct negative values were initialized also positive
} // keycodes had "soft" in the name.
try {
if (canvas.getKeyName(i).toUpperCase().indexOf("SOFT") < 0) {
continue;
}
if (canvas.getKeyName(i).indexOf("1") >= 0) {
leftSK[0] = i;
leftInit = true;
}
if (canvas.getKeyName(i).indexOf("2") >= 0) {
rightSK[0] = i;
rightInit = true;
}
continue;
} catch (Exception ex) {
}
}
}
/**
* Some devices (iden) map the fire key incorrectly, this method allows
* us to add another button as fire for specific devices.
*
* @param key keyCode to react as fire
*/
void setFireValue(int key) {
try {
getKeyCode(0);
} catch (Exception ignor) {
}
portableKeyCodeValues[4] = key;
}
/**
* @inheritDoc
*/
public void vibrate(final int duration) {
// prevent double calls to vibrate since some devices (e.g. Samsung 6503)
// crash when we do that
long now = System.currentTimeMillis();
if(now > lastVibrate) {
lastVibrate = now + (duration * 3);
display.vibrate(duration);
}
}
/**
* @inheritDoc
*/
public void flashBacklight(int duration) {
display.flashBacklight(duration);
}
/**
* @inheritDoc
*/
public int getDisplayWidth() {
return canvas.getWidth();
}
/**
* @inheritDoc
*/
public int getDisplayHeight() {
return canvas.getHeight();
}
/**
* @inheritDoc
*/
public void editString(Component cmp, int maxSize, int constraint, String text, int keyCode) {
UIManager m = UIManager.getInstance();
CONFIRM_COMMAND = new Command(m.localize("ok", "OK"), Command.OK, 1);
CANCEL_COMMAND = new Command(m.localize("cancel", "Cancel"), Command.CANCEL, 2);
currentTextBox = new TextBox("", "", maxSize, TextArea.ANY);
currentTextBox.setCommandListener((CommandListener)canvas);
currentTextBox.addCommand(CONFIRM_COMMAND);
currentTextBox.addCommand(CANCEL_COMMAND);
currentTextComponent = cmp;
currentTextBox.setMaxSize(maxSize);
currentTextBox.setString(text);
currentTextBox.setConstraints(constraint);
display.setCurrent(currentTextBox);
((C)canvas).setDone(false);
Display.getInstance().invokeAndBlock(((C)canvas));
}
/**
* @inheritDoc
*/
public void saveTextEditingState() {
if(currentTextBox != null) {
String text = currentTextBox.getString();
getCurrentForm().setVisible(true);
Display.getInstance().onEditingComplete(currentTextComponent, text);
currentTextBox = null;
((C)canvas).setDone(true);
}
}
/**
* Indicate to the implementation whether the flush graphics bug exists on this
* device. By default the flushGraphics bug is set to "true" and only disabled
* on handsets known 100% to be safe
*
* @param flushGraphicsBug true if the bug exists on this device (the safe choice)
* false for slightly higher performance.
*/
public void setFlashGraphicsBug(boolean flushGraphicsBug) {
this.flushGraphicsBug = flushGraphicsBug;
}
/**
* Allows subclasses to access the canvas
*
* @returns the canvas instance
*/
protected final Canvas getCanvas() {
return canvas;
}
/**
* @inheritDoc
*/
public void flushGraphics(int x, int y, int width, int height) {
// disable flush graphics bug when media is playing to prevent the double buffer
// from clearing the media and producing flickering
Form current = getCurrentForm();
if (!flushGraphicsBug || (current != null && current.hasMedia())) {
((C) canvas).flushGraphics(x, y, width, height);
} else {
((C) canvas).flushGraphics();
}
}
/**
* @inheritDoc
*/
public void flushGraphics() {
((C) canvas).flushGraphics();
}
/**
* @inheritDoc
*/
public void getRGB(Object nativeImage, int[] arr, int offset, int x, int y, int width, int height) {
((javax.microedition.lcdui.Image) nativeImage).getRGB(arr, offset, width, x, y, width, height);
}
/**
* @inheritDoc
*/
public Object createImage(
int[] rgb, int width, int height) {
return javax.microedition.lcdui.Image.createRGBImage(rgb, width, height, true);
}
/**
* @inheritDoc
*/
public Object createImage(
String path) throws IOException {
return javax.microedition.lcdui.Image.createImage(path);
}
/**
* @inheritDoc
*/
public Object createImage(
InputStream i) throws IOException {
return javax.microedition.lcdui.Image.createImage(i);
}
/**
* @inheritDoc
*/
public Object createMutableImage(
int width, int height, int fillColor) {
javax.microedition.lcdui.Image i = javax.microedition.lcdui.Image.createImage(width, height);
if (fillColor != 0xffffffff) {
javax.microedition.lcdui.Graphics g = i.getGraphics();
g.setColor(fillColor);
g.fillRect(0, 0, width, height);
g.drawRect(0, 0, width-1, height-1);
}
return i;
}
/**
* @inheritDoc
*/
public Object createImage(
byte[] bytes, int offset, int len) {
return javax.microedition.lcdui.Image.createImage(bytes, offset, len);
}
/**
* @inheritDoc
*/
public int getImageWidth(Object i) {
return ((javax.microedition.lcdui.Image) i).getWidth();
}
/**
* @inheritDoc
*/
public int getImageHeight(Object i) {
return ((javax.microedition.lcdui.Image) i).getHeight();
}
/**
* @inheritDoc
*/
public Object scale(
Object nativeImage, int width, int height) {
javax.microedition.lcdui.Image image = (javax.microedition.lcdui.Image) nativeImage;
int srcWidth = image.getWidth();
int srcHeight = image.getHeight();
// no need to scale
if (srcWidth == width && srcHeight == height) {
return image;
}
int[] currentArray = new int[srcWidth];
int[] destinationArray = new int[width * height];
scaleArray(image, srcWidth, srcHeight, height, width, currentArray, destinationArray);
return createImage(destinationArray, width, height);
}
private void scaleArray(javax.microedition.lcdui.Image currentImage, int srcWidth, int srcHeight, int height, int width, int[] currentArray, int[] destinationArray) {
// Horizontal Resize
int yRatio = (srcHeight << 16) / height;
int xRatio = (srcWidth << 16) / width;
int xPos = xRatio / 2;
int yPos = yRatio / 2;
// if there is more than 16bit color there is no point in using mutable
// images since they won't save any memory
for (int y = 0; y <
height; y++) {
int srcY = yPos >> 16;
getRGB(currentImage, currentArray, 0, 0, srcY, srcWidth, 1);
for (int x = 0; x <
width; x++) {
int srcX = xPos >> 16;
int destPixel = x + y * width;
if ((destPixel >= 0 && destPixel < destinationArray.length) && (srcX < currentArray.length)) {
destinationArray[destPixel] = currentArray[srcX];
}
xPos += xRatio;
}
yPos += yRatio;
xPos =
xRatio / 2;
}
}
/**
* @inheritDoc
*/
public void drawImageRotated(Object graphics, Object img, int x, int y, int degrees) {
javax.microedition.lcdui.Image i = (javax.microedition.lcdui.Image) img;
int t;
switch (degrees % 360) {
case 0:
drawImage(graphics, img, x, y);
return;
case 90:
t = Sprite.TRANS_ROT90;
break;
case 180:
t = Sprite.TRANS_ROT180;
break;
case 270:
t = Sprite.TRANS_ROT270;
break;
default:
throw new IllegalArgumentException("Unsupported value for drawImageRotated: " + degrees);
}
javax.microedition.lcdui.Graphics nativeGraphics = (javax.microedition.lcdui.Graphics) graphics;
nativeGraphics.drawRegion(i, 0, 0, i.getWidth(),
i.getHeight(), t, x, y,
javax.microedition.lcdui.Graphics.TOP | javax.microedition.lcdui.Graphics.LEFT);
}
/**
* @inheritDoc
*/
public boolean isRotationDrawingSupported() {
return true;
}
/**
* @inheritDoc
*/
public int getSoftkeyCount() {
return 2;
}
/**
* @inheritDoc
*/
public int[] getSoftkeyCode(int index) {
if (index == 0) {
return leftSK;
}
if (index == 1) {
return rightSK;
}
return null;
}
/**
* @inheritDoc
*/
public int getClearKeyCode() {
return clearSK;
}
/**
* @inheritDoc
*/
public int getBackspaceKeyCode() {
return backspaceSK;
}
/**
* @inheritDoc
*/
public int getBackKeyCode() {
return backSK;
}
/**
* @inheritDoc
*/
public int getGameAction(int keyCode) {
try {
// prevent game actions from being returned by numeric keypad thus screwing up
// keypad based navigation and text input
if (keyCode >= '0') {
return 0;
}
if (portableKeyCodes != null) {
for (int iter = 0; iter <
portableKeyCodeValues.length; iter++) {
if (portableKeyCodeValues[iter] == keyCode) {
return portableKeyCodes[iter];
}
}
}
return canvas.getGameAction(keyCode);
} catch (IllegalArgumentException err) {
// this is a stupid MIDP requirement some implementations throw this
// exception for some keys
return 0;
}
}
/**
* @inheritDoc
*/
public int getKeyCode(int gameAction) {
if (portableKeyCodes == null) {
portableKeyCodes = new int[]{Display.GAME_DOWN, Display.GAME_LEFT, Display.GAME_RIGHT, Display.GAME_UP, Display.GAME_FIRE};
portableKeyCodeValues = new int[5];
int currentValue = -500;
int offset = 0;
while (offset < portableKeyCodeValues.length) {
currentValue--;
try {
if (canvas.getGameAction(currentValue) != 0) {
continue;
}
} catch (IllegalArgumentException ignor) {
// this is good, the game key is unassigned
}
portableKeyCodeValues[offset] = currentValue;
offset++;
}
}
for (int iter = 0; iter <
portableKeyCodes.length; iter++) {
if (portableKeyCodes[iter] == gameAction) {
return portableKeyCodeValues[iter];
}
}
return 0;
}
/**
* @inheritDoc
*/
public boolean isTouchDevice() {
return canvas.hasPointerEvents();
}
/**
* @inheritDoc
*/
public void setNativeFont(Object graphics, Object font) {
javax.microedition.lcdui.Graphics nativeGraphics = (javax.microedition.lcdui.Graphics) graphics;
nativeGraphics.setFont(font(font));
}
/**
* @inheritDoc
*/
public int getClipX(Object graphics) {
javax.microedition.lcdui.Graphics nativeGraphics = (javax.microedition.lcdui.Graphics) graphics;
return nativeGraphics.getClipX();
}
/**
* @inheritDoc
*/
public int getClipY(Object graphics) {
javax.microedition.lcdui.Graphics nativeGraphics = (javax.microedition.lcdui.Graphics) graphics;
return nativeGraphics.getClipY();
}
/**
* @inheritDoc
*/
public int getClipWidth(Object graphics) {
javax.microedition.lcdui.Graphics nativeGraphics = (javax.microedition.lcdui.Graphics) graphics;
return nativeGraphics.getClipWidth();
}
/**
* @inheritDoc
*/
public int getClipHeight(Object graphics) {
javax.microedition.lcdui.Graphics nativeGraphics = (javax.microedition.lcdui.Graphics) graphics;
return nativeGraphics.getClipHeight();
}
/**
* @inheritDoc
*/
public void setClip(Object graphics, int x, int y, int width, int height) {
javax.microedition.lcdui.Graphics nativeGraphics = (javax.microedition.lcdui.Graphics) graphics;
nativeGraphics.setClip(x, y, width, height);
}
/**
* @inheritDoc
*/
public void clipRect(Object graphics, int x, int y, int width, int height) {
javax.microedition.lcdui.Graphics nativeGraphics = (javax.microedition.lcdui.Graphics) graphics;
nativeGraphics.clipRect(x, y, width, height);
}
/**
* @inheritDoc
*/
public void drawLine(Object graphics, int x1, int y1, int x2, int y2) {
javax.microedition.lcdui.Graphics nativeGraphics = (javax.microedition.lcdui.Graphics) graphics;
nativeGraphics.drawLine(x1, y1, x2, y2);
}
/**
* @inheritDoc
*/
public void fillRect(Object graphics, int x, int y, int w, int h) {
if (isAlphaGlobal()) {
javax.microedition.lcdui.Graphics nativeGraphics = (javax.microedition.lcdui.Graphics) graphics;
nativeGraphics.fillRect(x, y, w, h);
nativeGraphics.drawRect(x, y, w-1, h-1);
return;
}
if (alpha == 0) {
return;
}
if (alpha == 0xff) {
javax.microedition.lcdui.Graphics nativeGraphics = (javax.microedition.lcdui.Graphics) graphics;
nativeGraphics.fillRect(x, y, w, h);
nativeGraphics.drawRect(x, y, w-1, h-1);
} else {
int transparencyLevel = alpha << 24;
int color = (getColor(graphics) & 0x00FFFFFF);
color = (color | transparencyLevel);
if (rgbArr == null || rgbArr.length < w) {
rgbArr = new int[w];
}
for (int i = 0; i <
w; i++) {
rgbArr[i] = color;
}
int rgbX = x;
int rgbY = y;
if (rgbX < 0 && rgbX + w > 0) {
w = rgbX + w;
rgbX = 0;
}
if (w < 0) {
return;
}
int clipY = getClipY(graphics);
int clipHeight = getClipHeight(graphics);
int clipBottomY = clipHeight + clipY;
for (int i = 0; i < h; i++) {
if (rgbX >= 0 && rgbY + i >= 0) {
int currentY = rgbY + i;
if(currentY >= clipY && currentY <= clipBottomY) {
drawRGB(graphics, rgbArr, 0, rgbX, currentY, w, 1, true);
}
}
}
}
}
/**
* @inheritDoc
*/
public void drawRect(Object graphics, int x, int y, int width, int height) {
javax.microedition.lcdui.Graphics nativeGraphics = (javax.microedition.lcdui.Graphics) graphics;
nativeGraphics.drawRect(x, y, width, height);
}
/**
* @inheritDoc
*/
public void drawRoundRect(Object graphics, int x, int y, int width, int height, int arcWidth, int arcHeight) {
javax.microedition.lcdui.Graphics nativeGraphics = (javax.microedition.lcdui.Graphics) graphics;
nativeGraphics.drawRoundRect(x, y, width, height, arcWidth, arcHeight);
}
/**
* @inheritDoc
*/
public void fillRoundRect(Object graphics, int x, int y, int width, int height, int arcWidth, int arcHeight) {
javax.microedition.lcdui.Graphics nativeGraphics = (javax.microedition.lcdui.Graphics) graphics;
nativeGraphics.fillRoundRect(x, y, width, height, arcWidth, arcHeight);
}
/**
* @inheritDoc
*/
public void fillArc(Object graphics, int x, int y, int width, int height, int startAngle, int arcAngle) {
javax.microedition.lcdui.Graphics nativeGraphics = (javax.microedition.lcdui.Graphics) graphics;
nativeGraphics.fillArc(x, y, width, height, startAngle, arcAngle);
}
/**
* @inheritDoc
*/
public void drawArc(Object graphics, int x, int y, int width, int height, int startAngle, int arcAngle) {
javax.microedition.lcdui.Graphics nativeGraphics = (javax.microedition.lcdui.Graphics) graphics;
nativeGraphics.drawArc(x, y, width, height, startAngle, arcAngle);
}
/**
* @inheritDoc
*/
public void setColor(Object graphics, int RGB) {
javax.microedition.lcdui.Graphics nativeGraphics = (javax.microedition.lcdui.Graphics) graphics;
nativeGraphics.setColor(RGB);
}
/**
* @inheritDoc
*/
public int getColor(Object graphics) {
javax.microedition.lcdui.Graphics nativeGraphics = (javax.microedition.lcdui.Graphics) graphics;
return nativeGraphics.getColor();
}
/**
* @inheritDoc
*/
public void setAlpha(Object graphics, int alpha) {
this.alpha = alpha;
}
/**
* @inheritDoc
*/
public int getAlpha(Object graphics) {
return alpha;
}
/**
* @inheritDoc
*/
public void drawString(Object graphics, String str, int x, int y) {
javax.microedition.lcdui.Graphics nativeGraphics = (javax.microedition.lcdui.Graphics) graphics;
nativeGraphics.drawString(str, x, y, javax.microedition.lcdui.Graphics.TOP | javax.microedition.lcdui.Graphics.LEFT);
}
/**
* @inheritDoc
*/
public void drawImage(Object graphics, Object img, int x, int y) {
javax.microedition.lcdui.Graphics nativeGraphics = (javax.microedition.lcdui.Graphics) graphics;
nativeGraphics.drawImage((javax.microedition.lcdui.Image) img, x, y, javax.microedition.lcdui.Graphics.TOP | javax.microedition.lcdui.Graphics.LEFT);
}
/**
* @inheritDoc
*/
public void fillTriangle(Object graphics, int x1, int y1, int x2, int y2, int x3, int y3) {
javax.microedition.lcdui.Graphics nativeGraphics = (javax.microedition.lcdui.Graphics) graphics;
nativeGraphics.fillTriangle(x1, y1, x2, y2, x3, y3);
}
/**
* @inheritDoc
*/
public void drawRGB(Object graphics, int[] rgbData, int offset, int x, int y, int w, int h, boolean processAlpha) {
javax.microedition.lcdui.Graphics nativeGraphics = (javax.microedition.lcdui.Graphics) graphics;
int rgbX = x;
int rgbY = y;
//if the x or y are positive simply redirect the call to midp Graphics
if (rgbX >= 0 && rgbY >= 0) {
nativeGraphics.drawRGB(rgbData, offset, w, rgbX, rgbY, w, h, processAlpha);
return;
}
//first time try to draw with negative indexes
if (drawNegativeOffsetsInRGB) {
try {
nativeGraphics.drawRGB(rgbData, offset, w, rgbX, rgbY, w, h, processAlpha);
return;
} catch (RuntimeException e) {
//if you failed it might be because you tried to paint with negative
//indexes
drawNegativeOffsetsInRGB = false;
}
}
//if the translate causes us to paint out of the bounds
//we will paint only the relevant rows row by row to avoid some devices bugs
//such as BB that fails to paint if the coordinates are negative.
if (rgbX < 0 && rgbX + w > 0) {
if (w < rgbData.length) {
for (int i = 1; i <=
rgbData.length / w; i++) {
offset = -rgbX + (w * (i - 1));
rgbY++;
if (rgbY >= 0) {
nativeGraphics.drawRGB(rgbData, offset, (w + rgbX), 0, rgbY, w + rgbX, 1, processAlpha);
}
}
}
}
}
/**
* @inheritDoc
*/
public Object getVideoControl(
Object player) {
VideoControl vidc = (VideoControl) ((Player) player).getControl("VideoControl");
vidc.initDisplayMode(VideoControl.USE_DIRECT_VIDEO, canvas);
return vidc;
}
/**
* @inheritDoc
*/
public int numAlphaLevels() {
return display.numAlphaLevels();
}
/**
* @inheritDoc
*/
public int numColors() {
return display.numColors();
}
/**
* @inheritDoc
*/
public void playDialogSound(int type) {
type--;
if(type >= 0 && type < TYPES.length) {
TYPES[type].playSound(display);
}
}
/**
* @inheritDoc
*/
public void confirmControlView() {
if (display == null) {
throw new IllegalStateException("First call Display.setDisplay(javax.microedition.lcdui.Display d) method");
}
if (display.getCurrent() != canvas || !canvas.isShown()) {
setCurrent(canvas);
}
}
/**
* @inheritDoc
*/
private void setCurrent(Displayable d) {
if (display == null) {
throw new IllegalStateException("First call Display.setDisplay(javax.microedition.lcdui.Display d) method");
}
if(!minimized) {
if (d instanceof Canvas) {
((Canvas) d).setFullScreenMode(!com.sun.lwuit.Display.getInstance().isNativeCommands());
}
display.setCurrent(d);
}
}
/**
* @inheritDoc
*/
public Object getNativeGraphics() {
return ((C) canvas).getGraphics();
}
/**
* @inheritDoc
*/
public Object getNativeGraphics(
Object image) {
return ((javax.microedition.lcdui.Image) image).getGraphics();
}
/**
* @inheritDoc
*/
public void translate(Object graphics, int x, int y) {
// does nothing, we expect translate to occur in the graphics for
// better device portability
}
/**
* @inheritDoc
*/
public int getTranslateX(Object graphics) {
return 0;
}
/**
* @inheritDoc
*/
public int getTranslateY(Object graphics) {
return 0;
}
/**
* @inheritDoc
*/
public int charsWidth(Object nativeFont, char[] ch, int offset, int length) {
if(NOKIA) {
// charsWidth is MUCH MUCH MUCH slower on S40 devices than stringWidth.
return font(nativeFont).stringWidth(new String(ch, offset, length));
}
return font(nativeFont).charsWidth(ch, offset, length);
}
/**
* @inheritDoc
*/
public int stringWidth(Object nativeFont, String str) {
return font(nativeFont).stringWidth(str);
}
/**
* @inheritDoc
*/
public int charWidth(Object nativeFont, char ch) {
return font(nativeFont).charWidth(ch);
}
/**
* @inheritDoc
*/
public int getHeight(Object nativeFont) {
return font(nativeFont).getHeight();
}
/**
* @inheritDoc
*/
public Object createFont(
int face, int style, int size) {
return javax.microedition.lcdui.Font.getFont(face, style, size);
}
/**
* @inheritDoc
*/
public Object getDefaultFont() {
return javax.microedition.lcdui.Font.getDefaultFont();
}
/**
* @inheritDoc
*/
public int getFace(Object nativeFont) {
return font(nativeFont).getFace();
}
/**
* @inheritDoc
*/
public int getSize(Object nativeFont) {
return font(nativeFont).getSize();
}
/**
* @inheritDoc
*/
public int getStyle(Object nativeFont) {
return font(nativeFont).getStyle();
}
private javax.microedition.lcdui.Font font(Object f) {
if (f == null) {
return (javax.microedition.lcdui.Font) getDefaultFont();
}
return (javax.microedition.lcdui.Font) f;
}
/**
* @inheritDoc
*/
public VideoComponent createVideoPeer(String url) throws IOException {
try {
Player p = Manager.createPlayer(url);
p.realize();
return new MIDPVideoComponent(p);
} catch (MediaException ex) {
ex.printStackTrace();
throw new IOException(ex.toString());
}
}
/**
* @inheritDoc
*/
public VideoComponent createVideoPeer(InputStream stream, String type) throws IOException {
try {
Player p = Manager.createPlayer(stream, type);
p.realize();
return new MIDPVideoComponent(p);
} catch (MediaException ex) {
ex.printStackTrace();
throw new IOException(ex.toString());
}
}
class MIDPVideoComponent extends VideoComponent {
private boolean fullscreen;
MIDPVideoComponent(Player p) {
super(p);
putClientProperty("Player", p);
}
public int getMediaDuration() {
return (int)(((Player) getNativePeer()).getDuration() / 1000);
}
public boolean isPlaying() {
return ((Player) getNativePeer()).getState() == Player.STARTED;
}
public void setVisible(boolean b) {
super.setVisible(b);
getVideoControl(this).setVisible(b);
}
/**
* @inheritDoc
*/
public void paint(com.sun.lwuit.Graphics g) {
if(isVisible()){
try {
VideoControl vidc = (VideoControl) getVideoControl(this);
if (isFullScreen()) {
vidc.setDisplayLocation(0, 0);
vidc.setDisplaySize(Display.getInstance().getDisplayWidth(), Display.getInstance().getDisplayHeight());
} else {
vidc.setDisplayLocation(getAbsoluteX(), getAbsoluteY());
int w = getWidth();
int h = getHeight();
if (vidc.getDisplayWidth() != w || vidc.getDisplayHeight() != h) {
vidc.setDisplaySize(w, h);
}
}
} catch (MediaException ex) {
ex.printStackTrace();
}
}
}
/**
* @inheritDoc
*/
protected Dimension calcPreferredSize() {
VideoControl v = getVideoControl(this);
return new Dimension(v.getDisplayWidth(), v.getDisplayHeight());
}
/**
* Start media playback implicitly setting the component to visible
*/
public void start() {
try {
getVideoControl(this).setVisible(true);
((Player) getNativePeer()).start();
} catch (MediaException ex) {
ex.printStackTrace();
throw new RuntimeException(ex.toString());
}
}
/**
* Stope media playback
*/
public void stop() {
try {
((Player) getNativePeer()).stop();
} catch (MediaException ex) {
ex.printStackTrace();
throw new RuntimeException(ex.toString());
}
}
/**
* Set the number of times the media should loop
*
* @param count the number of times the media should loop
*/
public void setLoopCount(int count) {
((Player) getNativePeer()).setLoopCount(count);
}
/**
* Return the duration of the media
*
* @return the duration of the media
*/
public int getMediaTimeMS() {
return (int)(((Player) getNativePeer()).getMediaTime() / 1000);
}
/**
* "Jump" to a point in time within the media
*
* @param now the point in time to "Jump" to
* @return the media time in microseconds
*/
public int setMediaTimeMS(int now) {
try {
return (int)(((Player) getNativePeer()).setMediaTime(now * 1000) / 1000);
} catch (MediaException ex) {
ex.printStackTrace();
throw new RuntimeException(ex.toString());
}
}
public void setFullScreen(boolean fullscreen) {
this.fullscreen = fullscreen;
repaint();
}
public boolean isFullScreen() {
return fullscreen;
}
}
private VideoControl getVideoControl(VideoComponent c) {
VideoControl vidc = (VideoControl)c.getClientProperty("VideoControl");
if(vidc != null) {
return vidc;
}
vidc = (VideoControl) ((Player) c.getNativePeer()).getControl("VideoControl");
vidc.initDisplayMode(VideoControl.USE_DIRECT_VIDEO, canvas);
c.putClientProperty("VideoControl", vidc);
return vidc;
}
/**
* @inheritDoc
*/
public Object createVideoComponent(
Object player) {
if (((Player) player).getState() < Player.REALIZED) {
throw new IllegalArgumentException("player must be in a realized state");
}
return getVideoControl(player);
}
/**
* @inheritDoc
*/
public int getVideoWidth(Object videoControl) {
return ((VideoControl) videoControl).getSourceWidth();
}
/**
* @inheritDoc
*/
public int getVideoHeight(Object videoControl) {
return ((VideoControl) videoControl).getSourceHeight();
}
/**
* @inheritDoc
*/
public void setVideoVisible(Object vc, boolean visible) {
((VideoControl) vc).setVisible(visible);
}
/**
* @inheritDoc
*/
public void startVideo(Object player, Object videoControl) {
try {
((VideoControl) videoControl).setVisible(true);
((Player) player).start();
} catch (MediaException ex) {
ex.printStackTrace();
}
}
/**
* @inheritDoc
*/
public void stopVideo(Object player, Object videoControl) {
try {
((Player) player).stop();
} catch (MediaException ex) {
ex.printStackTrace();
}
}
/**
* @inheritDoc
*/
public void setVideoLoopCount(Object player, int count) {
((Player) player).setLoopCount(count);
}
/**
* @inheritDoc
*/
public long getMediaTime(Object player) {
return ((Player) player).getMediaTime();
}
/**
* @inheritDoc
*/
public long setMediaTime(Object player, long now) {
try {
return ((Player) player).setMediaTime(now);
} catch (MediaException ex) {
ex.printStackTrace();
throw new RuntimeException(ex.toString());
}
}
/**
* @inheritDoc
*/
public void paintVideo(Component cmp, boolean fullScreen, Object nativeGraphics, Object video,
Object player) {
try {
VideoControl vidc = (VideoControl) video;
if (fullScreen) {
vidc.setDisplayLocation(0, 0);
vidc.setDisplaySize(Display.getInstance().getDisplayWidth(), Display.getInstance().getDisplayHeight());
} else {
vidc.setDisplayLocation(cmp.getAbsoluteX(), cmp.getAbsoluteY());
int w = cmp.getWidth();
int h = cmp.getHeight();
if (vidc.getDisplayWidth() != w || vidc.getDisplayHeight() != h) {
vidc.setDisplaySize(w, h);
}
}
} catch (MediaException ex) {
ex.printStackTrace();
}
}
/**
* @inheritDoc
*/
public boolean minimizeApplication() {
try {
minimized = true;
display.setCurrent(null);
} catch(Throwable t) {
t.printStackTrace();
}
return false;
}
/**
* @inheritDoc
*/
public void restoreMinimizedApplication() {
try {
minimized = false;
display.setCurrent(canvas);
} catch(Throwable t) {
t.printStackTrace();
}
}
/**
* @inheritDoc
*/
public boolean isMinimized() {
return minimized;
}
/**
* @inheritDoc
*/
public void showNativeScreen(Object nativeFullScreenPeer) {
display.setCurrent((Displayable)nativeFullScreenPeer);
}
/**
* @inheritDoc
*/
public void setNativeCommands(Vector commands) {
canvas.setFullScreenMode(!com.sun.lwuit.Display.getInstance().isNativeCommands());
((C)canvas).setCommands(commands);
}
/**
* Exits the application...
*/
public void exitApplication() {
mid.notifyDestroyed();
}
/**
* @inheritDoc
*/
public String getProperty(String key, String defaultValue) {
if("AppName".equals(key)) {
return mid.getAppProperty("MIDlet-Name");
}
if("AppVersion".equals(key)) {
return mid.getAppProperty("MIDlet-Version");
}
if("Platform".equals(key)) {
return System.getProperty("microedition.platform");
}
if("OS".equals(key)) {
return "J2ME";
}
if ("IMEI".equals(key)) {
String imei = null;
imei = System.getProperty("phone.imei");
if(imei != null){
return imei;
}
imei = System.getProperty("com.nokia.IMEI");
if(imei != null){
return imei;
}
imei = System.getProperty("com.nokia.mid.imei");
if(imei != null){
return imei;
}
imei = System.getProperty("com.sonyericsson.imei");
if(imei != null){
return imei;
}
imei = System.getProperty("IMEI");
if(imei != null){
return imei;
}
imei = System.getProperty("com.motorola.IMEI");
if(imei != null){
return imei;
}
imei = System.getProperty("com.samsung.imei");
if(imei != null){
return imei;
}
imei = System.getProperty("com.siemens.imei");
if(imei != null){
return imei;
}
imei = System.getProperty("com.lge.imei");
if(imei != null){
return imei;
}
}
String s = mid.getAppProperty(key);
if(s == null) {
return defaultValue;
}
return s;
}
/**
* @inheritDoc
*/
public void execute(String url) {
try {
mid.platformRequest(url);
} catch (ConnectionNotFoundException ex) {
ex.printStackTrace();
}
}
/**
* @inheritDoc
*/
public void playBuiltinSound(String soundIdentifier) {
if(!playUserSound(soundIdentifier)) {
if(soundIdentifier.equals(Display.SOUND_TYPE_ALARM)) {
AlertType.ALARM.playSound(display);
return;
}
if(soundIdentifier.equals(Display.SOUND_TYPE_CONFIRMATION)) {
AlertType.CONFIRMATION.playSound(display);
return;
}
if(soundIdentifier.equals(Display.SOUND_TYPE_ERROR)) {
AlertType.ERROR.playSound(display);
return;
}
if(soundIdentifier.equals(Display.SOUND_TYPE_INFO)) {
AlertType.INFO.playSound(display);
return;
}
if(soundIdentifier.equals(Display.SOUND_TYPE_WARNING)) {
AlertType.WARNING.playSound(display);
return;
}
}
}
/**
* @inheritDoc
*/
protected void playNativeBuiltinSound(Object data) {
try {
try {
Object o = createAudio(new ByteArrayInputStream((byte[]) data), "audio/mpeg", null);
playAudio(o);
} catch(Exception err) {
// some simulators take issue with the audio/mpeg string but the mp3 string
// works fine
Object o = createAudio(new ByteArrayInputStream((byte[]) data), "audio/mp3", null);
playAudio(o);
}
} catch (IOException ex) {
// not likely since the stream is a byte array input stream
ex.printStackTrace();
}
}
/**
* @inheritDoc
*/
public boolean isBuiltinSoundAvailable(String soundIdentifier) {
if(soundIdentifier.equals(Display.SOUND_TYPE_ALARM)) {
return true;
}
if(soundIdentifier.equals(Display.SOUND_TYPE_CONFIRMATION)) {
return true;
}
if(soundIdentifier.equals(Display.SOUND_TYPE_ERROR)) {
return true;
}
if(soundIdentifier.equals(Display.SOUND_TYPE_INFO)) {
return true;
}
if(soundIdentifier.equals(Display.SOUND_TYPE_WARNING)) {
return true;
}
return super.isBuiltinSoundAvailable(soundIdentifier);
}
/**
* @inheritDoc
*/
public Object createAudio(String uri, Runnable onCompletion) throws IOException {
return MMAPIPlayer.createAudio(uri, onCompletion);
}
/**
* @inheritDoc
*/
public Object createAudio(InputStream stream, String mimeType, Runnable onCompletion) throws IOException {
return MMAPIPlayer.createAudio(stream, mimeType, onCompletion);
}
/**
* @inheritDoc
*/
public void cleanupAudio(Object handle) {
((MMAPIPlayer)handle).cleanupAudio();
}
/**
* @inheritDoc
*/
public void playAudio(Object handle) {
((MMAPIPlayer)handle).playAudio();
}
/**
* @inheritDoc
*/
public void pauseAudio(Object handle) {
((MMAPIPlayer)handle).pauseAudio();
}
/**
* @inheritDoc
*/
public int getAudioTime(Object handle) {
return ((MMAPIPlayer)handle).getAudioTime();
}
/**
* @inheritDoc
*/
public void setAudioTime(Object handle, int time) {
((MMAPIPlayer)handle).setAudioTime(time);
}
/**
* @inheritDoc
*/
public int getAudioDuration(Object handle) {
return ((MMAPIPlayer)handle).getAudioDuration();
}
/**
* @inheritDoc
*/
public void setVolume(int vol) {
MMAPIPlayer.setVolume(vol);
}
/**
* @inheritDoc
*/
public int getVolume() {
return MMAPIPlayer.getVolume();
}
}