/*
* 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.codename1.impl.midp;
import com.codename1.impl.midp.codescan.CodeScannerImpl;
import com.codename1.codescan.CodeScanner;
import com.codename1.components.MediaPlayer;
import com.codename1.contacts.Contact;
import com.codename1.impl.CodenameOneImplementation;
import com.codename1.impl.midp.codescan.ScannerHider;
import com.codename1.messaging.Message;
import com.codename1.ui.Component;
import com.codename1.ui.Display;
import com.codename1.ui.Form;
import com.codename1.ui.Graphics;
import com.codename1.ui.TextArea;
import com.codename1.ui.events.ActionEvent;
import com.codename1.ui.events.ActionListener;
import com.codename1.ui.geom.Dimension;
import com.codename1.ui.plaf.UIManager;
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.MediaException;
import javax.microedition.media.PlayerListener;
import javax.microedition.midlet.MIDlet;
import javax.microedition.media.control.VideoControl;
import com.codename1.io.BufferedInputStream;
import com.codename1.io.BufferedOutputStream;
import com.codename1.io.FileSystemStorage;
import com.codename1.io.MultipartRequest;
import com.codename1.io.Util;
import com.codename1.l10n.L10NManager;
import com.codename1.location.LocationManager;
import com.codename1.media.Media;
import com.codename1.ui.*;
import com.codename1.ui.animations.Animation;
import com.codename1.ui.animations.CommonTransitions;
import com.codename1.ui.layouts.BorderLayout;
import com.codename1.ui.util.Resources;
import com.codename1.util.StringUtil;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Date;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import javax.microedition.io.Connection;
import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;
import javax.microedition.io.file.FileConnection;
import javax.microedition.io.file.FileSystemRegistry;
import javax.microedition.media.control.RecordControl;
import javax.microedition.rms.RecordEnumeration;
import javax.microedition.rms.RecordStore;
import javax.microedition.rms.RecordStoreException;
import javax.wireless.messaging.MessageConnection;
import javax.wireless.messaging.TextMessage;
/**
* An implementation of Codename One based on game canvas, this is the default implementation
* class for Codename One which most customizers should extend to enhance.
*
* @author Shai Almog
*/
public class GameCanvasImplementation extends CodenameOneImplementation {
private static boolean NOKIA = false;
private boolean minimized;
private MIDlet mid;
private Object currentlyPlayingAudio;
private short currentKey = 1;
/**
* The File Allocation Table assigns user based file names to RMS storage
*/
private Hashtable fat = new Hashtable();
/**
* 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 ActionListener captureResponse;
private LocationManager location = null;
// if JSR 179 isn't supported then null already is the initialized state
private boolean locationInitialized = System.getProperty("microedition.location.version") == null;
static final javax.microedition.lcdui.Command MIDP_BACK_COMMAND = new javax.microedition.lcdui.Command("Back", Command.BACK, 1);
private class C extends GameCanvas implements CommandListener, Runnable {
private boolean done;
private Command[] currentCommands;
class MIDP2CodenameOneCommand extends Command {
com.codename1.ui.Command internal;
public MIDP2CodenameOneCommand(com.codename1.ui.Command c, int offset) {
super(c.getCommandName(), Command.SCREEN, offset);
internal = c;
}
public MIDP2CodenameOneCommand(com.codename1.ui.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.codename1.ui.Command backCommand = null;
if(Display.getInstance().getCurrent() != null) {
backCommand = Display.getInstance().getCurrent().getBackCommand();
}
for(int iter = 0 ; iter < currentCommands.length ; iter++) {
com.codename1.ui.Command current = (com.codename1.ui.Command)v.elementAt(iter);
if(current == backCommand) {
currentCommands[iter] = new MIDP2CodenameOneCommand(current, Command.BACK, iter + 1);
} else {
if(iter == 0) {
currentCommands[iter] = new MIDP2CodenameOneCommand(current, Command.OK, iter + 1);
} else {
currentCommands[iter] = new MIDP2CodenameOneCommand(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 == MIDP_BACK_COMMAND) {
GameCanvasImplementation.this.keyPressed(backSK);
GameCanvasImplementation.this.keyReleased(backSK);
return;
}
if(c instanceof MIDP2CodenameOneCommand) {
final com.codename1.ui.Command cmd = ((MIDP2CodenameOneCommand)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;
public static boolean disableFullScreen;
/**
* 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);
if(!disableFullScreen) {
canvas.setFullScreenMode(!com.codename1.ui.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);
//nokia devices cannot use OutputStreamWriter flush when using
//MultipartRequest
MultipartRequest.setCanFlushStream(false);
} else {
flushGraphicsBug = true;
Display.getInstance().setTransitionYield(-1);
}
mid = (MIDlet)m;
display = javax.microedition.lcdui.Display.getDisplay(mid);
setSoftKeyCodes(mid);
if(mid.getAppProperty("forceBackCommand") != null) {
canvas.setCommandListener((CommandListener) canvas);
canvas.addCommand(MIDP_BACK_COMMAND);
}
RecordEnumeration e = null;
RecordStore r = null;
try {
r = RecordStore.openRecordStore("FAT", true);
if (r.getNumRecords() > 0) {
e = r.enumerateRecords(null, null, false);
while (e.hasNextElement()) {
byte[] rec = e.nextRecord();
ByteArrayInputStream bi = new ByteArrayInputStream(rec);
DataInputStream di = new DataInputStream(bi);
String name = di.readUTF();
short key = di.readShort();
di.close();
bi.close();
fat.put(name, new Short(key));
if(key >= currentKey) {
currentKey += key;
}
}
e.destroy();
e = null;
}
r.closeRecordStore();
r = null;
} catch (Exception ex) {
ex.printStackTrace();
cleanup(r);
cleanup(e);
}
}
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);
if(mid.getAppProperty("forceBackCommand") != null) {
canvas.addCommand(MIDP_BACK_COMMAND);
}
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 {
if(path.startsWith("file:") && exists(path)){
InputStream is = null;
try {
is = openInputStream(path);
return createImage(is);
} finally {
is.close();
}
}
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 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) {
if(!disableFullScreen) {
((Canvas) d).setFullScreenMode(!com.codename1.ui.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();
}
public int getFontAscent(Object nativeFont) {
return Math.abs(font(nativeFont).getBaselinePosition());
}
public int getFontDescent(Object nativeFont) {
return Math.abs(getHeight(nativeFont)-getFontAscent(nativeFont));
}
/**
* @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;
}
/**
* This method returns the platform Location Control
* @return LocationControl Object
*/
public LocationManager getLocationManager() {
if(!locationInitialized) {
locationInitialized = true;
try {
location = LocationHider.createLocationManager();
} catch(Throwable t) {}
}
return location;
}
public static class MIDPVideoComponent extends Component implements Media{
private boolean fullscreen;
private PlayerListener l;
private MMAPIPlayer player;
private boolean nativePlayer;
private Form curentForm;
private Object canvas;
public MIDPVideoComponent(MMAPIPlayer player, Object canvas) {
this.player = player;
this.canvas = canvas;
putClientProperty("nativePlayer", player.nativePlayer);
}
public int getDuration() {
return player.getDuration();
}
public void setVisible(boolean b) {
super.setVisible(b);
getVideoControl(this).setVisible(b);
}
/**
* @inheritDoc
*/
protected void paintBackground(Graphics g) {
}
/**
* @inheritDoc
*/
public void paintBackgrounds(Graphics g) {
}
/**
* @inheritDoc
*/
protected void paintBorder(Graphics g) {
}
/**
* @inheritDoc
*/
protected void paintScrollbarX(Graphics g) {
}
/**
* @inheritDoc
*/
protected void paintScrollbarY(Graphics g) {
}
/**
* @inheritDoc
*/
protected void paintScrollbars(Graphics g) {
}
/**
* @inheritDoc
*/
public void paint(com.codename1.ui.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 play() {
if(nativePlayer && curentForm == null){
curentForm = Display.getInstance().getCurrent();
Form f = new Form();
f.setLayout(new BorderLayout());
f.addComponent(BorderLayout.CENTER, new MediaPlayer(this));
f.show();
}
player.play();
}
public void prepare() {
player.prepare();
}
/**
* Stope media playback
*/
public void pause() {
player.pause();
}
/**
* Return the duration of the media
*
* @return the duration of the media
*/
public int getTime() {
return player.getTime();
}
/**
* "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 void setTime(int now) {
player.setTime(now);
}
public void setFullScreen(boolean fullscreen) {
this.fullscreen = fullscreen;
repaint();
}
public boolean isFullScreen() {
return fullscreen;
}
public void cleanup() {
player.cleanup();
putClientProperty("nativePlayer", null);
if(nativePlayer && curentForm != null){
curentForm.showBack();
curentForm = null;
}
}
private VideoControl getVideoControl(Component c) {
VideoControl vidc = (VideoControl) c.getClientProperty("VideoControl");
if (vidc != null) {
return vidc;
}
vidc = (VideoControl) player.nativePlayer.getControl("VideoControl");
vidc.initDisplayMode(VideoControl.USE_DIRECT_VIDEO, canvas);
c.putClientProperty("VideoControl", vidc);
return vidc;
}
public void setVolume(int vol) {
player.setVolume(vol);
}
public int getVolume() {
return player.getVolume();
}
public Component getVideoComponent() {
setVisible(true);
return this;
}
public boolean isVideo() {
return true;
}
public void setNativePlayerMode(boolean nativePlayer) {
this.nativePlayer = nativePlayer;
}
public boolean isNativePlayerMode() {
return nativePlayer;
}
public boolean isPlaying() {
return player.isPlaying();
}
public void setVariable(String key, Object value) {
}
public Object getVariable(String key) {
return null;
}
}
/**
* @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.codename1.ui.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("cellId".equals(key)) {
String s = System.getProperty("wireless.messaging.sms.smsc");
if(s != null) {
return s;
}
s = System.getProperty("com.nokia.mid.cellid");
if(s != null) {
return s;
}
s = System.getProperty("com.sonyericsson.net.cellid");
if(s != null) {
return s;
}
s = System.getProperty("com.samsung.cellid");
if(s != null) {
return s;
}
s = System.getProperty("com.siemens.cellid");
if(s != null) {
return s;
}
s = System.getProperty("com.lge.net.cellid");
if(s != null) {
return s;
}
}
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 {
Media m = createMedia(new ByteArrayInputStream((byte[]) data), "audio/mpeg", null);
m.play();
} catch(Exception err) {
// some simulators take issue with the audio/mpeg string but the mp3 string
// works fine
Media m = createMedia(new ByteArrayInputStream((byte[]) data), "audio/mp3", null);
m.play();
}
} 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);
}
/**
* Plays the sound in the given URI which is partially platform specific.
*
* @param uri the platform specific location for the sound
* @param onCompletion invoked when the audio file finishes playing, may be null
* @return a handle that can be used to control the playback of the audio
* @throws java.io.IOException if the URI access fails
*/
public Media createMedia(String uri, boolean isVideo, Runnable onCompletion) throws IOException {
MMAPIPlayer player = MMAPIPlayer.createPlayer(uri, onCompletion);
if(isVideo){
return new MIDPVideoComponent(player, canvas);
}
return player;
}
/**
* Plays the sound in the given stream
*
* @param stream the stream containing the media data
* @param mimeType the type of the data in the stream
* @param onCompletion invoked when the audio file finishes playing, may be null
* @return a handle that can be used to control the playback of the audio
* @throws java.io.IOException if the URI access fails
*/
public Media createMedia(InputStream stream, String mimeType, Runnable onCompletion) throws IOException {
MMAPIPlayer player = MMAPIPlayer.createPlayer(stream, mimeType, onCompletion);
if(mimeType.indexOf("video") > -1){
return new MIDPVideoComponent(player, canvas);
}
return player;
}
/**
* @inheritDoc
*/
public Object connect(String url, boolean read, boolean write) throws IOException {
int mode;
if(read && write) {
mode = Connector.READ_WRITE;
} else {
if(write) {
mode = Connector.WRITE;
} else {
mode = Connector.READ;
}
}
return Connector.open(url, mode);
}
/**
* @inheritDoc
*/
public void setHeader(Object connection, String key, String val) {
try {
((HttpConnection)connection).setRequestProperty(key, val);
} catch(IOException err) {
// this exception doesn't make sense since at this point no connection is in place
err.printStackTrace();
}
}
/**
* @inheritDoc
*/
public int getContentLength(Object connection) {
return (int)((HttpConnection)connection).getLength();
}
/**
* @inheritDoc
*/
public void cleanup(Object o) {
try {
if(o != null) {
if(o instanceof Connection) {
((Connection) o).close();
return;
}
if(o instanceof RecordEnumeration) {
((RecordEnumeration) o).destroy();
return;
}
if(o instanceof RecordStore) {
((RecordStore) o).closeRecordStore();
return;
}
super.cleanup(o);
}
} catch (Throwable ex) {
ex.printStackTrace();
}
}
/**
* @inheritDoc
*/
public OutputStream openOutputStream(Object connection) throws IOException {
if(connection instanceof String) {
FileConnection fc = (FileConnection)Connector.open((String)connection, Connector.READ_WRITE);
if(!fc.exists()) {
fc.create();
}
BufferedOutputStream o = new BufferedOutputStream(fc.openOutputStream(), (String)connection);
o.setConnection(fc);
return o;
}
return new BufferedOutputStream(((HttpConnection)connection).openOutputStream(), ((HttpConnection)connection).getURL());
}
/**
* @inheritDoc
*/
public OutputStream openOutputStream(Object connection, int offset) throws IOException {
FileConnection fc = (FileConnection)Connector.open((String)connection, Connector.READ_WRITE);
if(!fc.exists()) {
fc.create();
}
BufferedOutputStream o = new BufferedOutputStream(fc.openOutputStream(offset), (String)connection);
o.setConnection(fc);
return o;
}
/**
* @inheritDoc
*/
public InputStream openInputStream(Object connection) throws IOException {
if(connection instanceof String) {
FileConnection fc = (FileConnection)Connector.open((String)connection, Connector.READ);
BufferedInputStream o = new BufferedInputStream(fc.openInputStream(), (String)connection);
o.setConnection(fc);
return o;
}
return new BufferedInputStream(((HttpConnection)connection).openInputStream(), ((HttpConnection)connection).getURL());
}
/**
* @inheritDoc
*/
public void setHttpMethod(Object connection, String method) throws IOException {
((HttpConnection)connection).setRequestMethod(method);
}
/**
* @inheritDoc
*/
public void setPostRequest(Object connection, boolean p) {
try {
if(p) {
((HttpConnection)connection).setRequestMethod(HttpConnection.POST);
} else {
((HttpConnection)connection).setRequestMethod(HttpConnection.GET);
}
} catch(IOException err) {
// an exception here doesn't make sense
err.printStackTrace();
}
}
/**
* @inheritDoc
*/
public int getResponseCode(Object connection) throws IOException {
return ((HttpConnection)connection).getResponseCode();
}
/**
* @inheritDoc
*/
public String getResponseMessage(Object connection) throws IOException {
return ((HttpConnection)connection).getResponseMessage();
}
/**
* @inheritDoc
*/
public String getHeaderField(String name, Object connection) throws IOException {
return ((HttpConnection)connection).getHeaderField(name);
}
/**
* @inheritDoc
*/
public String[] getHeaderFieldNames(Object connection) throws IOException {
HttpConnection c = (HttpConnection)connection;
Vector r = new Vector();
int i = 0;
String key = c.getHeaderFieldKey(i);
while (key != null) {
if(r.indexOf(key) < 0) {
r.addElement(key);
}
i++;
key = c.getHeaderFieldKey(i);
}
if(r.size() == 0) {
return null;
}
String[] response = new String[r.size()];
for(int iter = 0 ; iter < response.length ; iter++) {
response[iter] = (String)r.elementAt(iter);
}
return response;
}
/**
* @inheritDoc
*/
public String[] getHeaderFields(String name, Object connection) throws IOException {
HttpConnection c = (HttpConnection)connection;
Vector r = new Vector();
int i = 0;
while (c.getHeaderFieldKey(i) != null) {
if (c.getHeaderFieldKey(i).equalsIgnoreCase(name)) {
String val = c.getHeaderField(i);
//some J2ME devices such as Nokia send all the cookies in one
//header spereated by commas
if(name.equalsIgnoreCase("Set-Cookie")){
//it is not possible to simply tokenize on comma, because
//the expiration date of each cookie contains a comma, therefore
//we temporary remove this comma tokenize all the cookies and then
//fixing the comma in the expiration date
String cookies = "";
Vector v = StringUtil.tokenizeString(val, ';');
for (int j = 0; j < v.size(); j++) {
String keyval = (String) v.elementAt(j);
if(keyval.indexOf("expires") > -1){
keyval = StringUtil.replaceAll(keyval, ",", "@__@");
}
cookies += keyval + ";";
}
cookies = cookies.substring(0, cookies.length() - 1);
if(cookies.indexOf(",") > -1){
Vector v2 = StringUtil.tokenizeString(cookies, ',');
for (int j = 0; j < v2.size(); j++) {
String value = (String) v2.elementAt(j);
value = StringUtil.replaceAll(value, "@__@", ",");
r.addElement(value);
}
}
}else{
r.addElement(val);
}
}
i++;
}
if(r.size() == 0) {
return null;
}
String[] response = new String[r.size()];
for(int iter = 0 ; iter < response.length ; iter++) {
response[iter] = (String)r.elementAt(iter);
}
return response;
}
/**
* @inheritDoc
*/
public void deleteStorageFile(String name) {
Short key = (Short)fat.get(name);
fat.remove(name);
resaveFat();
if(key != null) {
try {
for(char c = 'A' ; c < 'Z' ; c++) {
RecordStore.deleteRecordStore("" + c + key);
}
} catch(RecordStoreException e) {}
}
}
private void resaveFat() {
RecordStore r = null;
RecordEnumeration e = null;
try {
r = RecordStore.openRecordStore("FAT", true);
Vector keys = new Vector();
Enumeration fatKeys = fat.keys();
while(fatKeys.hasMoreElements()) {
keys.addElement(fatKeys.nextElement());
}
e = r.enumerateRecords(null, null, false);
while (e.hasNextElement()) {
int recordId = e.nextRecordId();
byte[] rec = r.getRecord(recordId);
ByteArrayInputStream bi = new ByteArrayInputStream(rec);
DataInputStream di = new DataInputStream(bi);
String name = di.readUTF();
short key = di.readShort();
di.close();
bi.close();
Short fatKey = (Short)fat.get(name);
if(fatKey == null) {
// we need to remove this record...
r.deleteRecord(recordId);
} else {
// we need to update the record
if(fatKey.shortValue() != key) {
byte[] bd = toRecord(name, fatKey.shortValue());
r.setRecord(recordId, bd, 0, bd.length);
}
}
keys.removeElement(name);
}
e.destroy();
e = null;
Enumeration remainingKeys = keys.elements();
while(remainingKeys.hasMoreElements()) {
String name = (String)remainingKeys.nextElement();
Short key = (Short)fat.get(name);
byte[] bd = toRecord(name, key.shortValue());
r.addRecord(bd, 0, bd.length);
}
r.closeRecordStore();
} catch(Exception err) {
// This might be a valid exception and some platforms (e..g. RIM) don't respond well to PST
//err.printStackTrace();
cleanup(e);
cleanup(r);
}
}
private byte[] toRecord(String name, short key) throws IOException {
ByteArrayOutputStream bo = new ByteArrayOutputStream();
DataOutputStream d = new DataOutputStream(bo);
d.writeUTF(name);
d.writeShort(key);
d.close();
bo.close();
return bo.toByteArray();
}
/**
* @inheritDoc
*/
public OutputStream openFileOutputStream(String file) throws IOException {
return openOutputStream(file);
}
/**
* @inheritDoc
*/
public InputStream openFileInputStream(String file) throws IOException {
return openInputStream(file);
}
private class RMSOutputStream extends OutputStream {
private short key;
private char letter = 'A';
private ByteArrayOutputStream cache;
public RMSOutputStream(short key) {
this.key = key;
// first we need to cleanup existing files
try {
for(char c = 'A' ; c < 'Z' ; c++) {
RecordStore.deleteRecordStore("" + c + key);
}
} catch(RecordStoreException e) {}
cache = new ByteArrayOutputStream();
}
public void close() throws IOException {
flush();
cache = null;
}
public void flush() throws IOException {
if(cache != null) {
byte[] data = cache.toByteArray();
if(data.length > 0) {
RecordStore r = null;
try {
r = RecordStore.openRecordStore("" + letter + key, true);
r.addRecord(data, 0, data.length);
r.closeRecordStore();
if(letter == 'Z') {
letter = 'a';
} else {
letter++;
}
cache = new ByteArrayOutputStream();
} catch (RecordStoreException ex) {
ex.printStackTrace();
cleanup(r);
throw new IOException(ex.toString());
}
}
}
}
public void write(byte[] arg0) throws IOException {
cache.write(arg0);
if(cache.size() > 32536) {
flush();
}
}
public void write(byte[] arg0, int arg1, int arg2) throws IOException {
cache.write(arg0, arg1, arg2);
if(cache.size() > 32536) {
flush();
}
}
public void write(int arg0) throws IOException {
cache.write(arg0);
if(cache.size() > 32536) {
flush();
}
}
}
private class RMSInputStream extends InputStream {
private InputStream current;
private int offset;
private short key;
public RMSInputStream(short key) throws IOException {
this.key = key;
RecordStore r = null;
RecordEnumeration e = null;
char letter = 'A';
try {
ByteArrayOutputStream os = new ByteArrayOutputStream();
r = open("" + letter + key);
while(r != null) {
e = r.enumerateRecords(null, null, false);
while(e.hasNextElement()) {
byte[] data = e.nextRecord();
os.write(data);
}
e.destroy();
r.closeRecordStore();
letter++;
r = open("" + letter + key);
if(letter == 'Z') {
letter = 'a' - ((char)1);
}
}
os.close();
current = new ByteArrayInputStream(os.toByteArray());
} catch (RecordStoreException ex) {
//#ifndef RIM
ex.printStackTrace();
//#else
//# System.out.println("Exception in object store input stream constructor: " + ex);
//#endif
cleanup(r);
cleanup(e);
throw new IOException(ex.toString());
}
}
private RecordStore open(String s) {
try {
return RecordStore.openRecordStore(s, false);
} catch (RecordStoreException ex) {
return null;
}
}
public long skip(long n) throws IOException {
return super.skip(n);
}
public void close() throws IOException {
current.close();
}
public int read(byte[] arg0) throws IOException {
int r = current.read(arg0);
offset += r;
return r;
}
public int read(byte[] arg0, int arg1, int arg2) throws IOException {
int r = current.read(arg0, arg1, arg2);
offset += r;
return r;
}
public int read() throws IOException {
offset++;
return current.read();
}
}
/**
* @inheritDoc
*/
public OutputStream createStorageOutputStream(String name) throws IOException {
RecordStore r = null;
RMSOutputStream os = null;
DataOutputStream out = null;
try {
Short key = (Short)fat.get(name);
if(key == null) {
// need to add a key to the FAT
key = new Short(currentKey);
fat.put(name, key);
r = RecordStore.openRecordStore("FAT", true);
byte[] data = toRecord(name, currentKey);
currentKey++;
r.addRecord(data, 0, data.length);
r.closeRecordStore();
r = null;
}
os = new RMSOutputStream(key.shortValue());
return os;
} catch(Exception err) {
cleanup(r);
cleanup(os);
cleanup(out);
throw new IOException(err.getMessage());
}
}
/**
* @inheritDoc
*/
public InputStream createStorageInputStream(String name) throws IOException {
Short key = (Short)fat.get(name);
if(key == null) {
return null;
}
try {
return new RMSInputStream(key.shortValue());
} catch(Exception err) {
err.printStackTrace();
}
return null;
}
/**
* @inheritDoc
*/
public boolean storageFileExists(String name) {
if(name == null) {
return false;
}
return fat.containsKey(name);
}
/**
* @inheritDoc
*/
public String[] listStorageEntries() {
String[] a = new String[fat.size()];
Enumeration e = fat.keys();
int i = 0;
while(e.hasMoreElements()) {
a[i] = (String)e.nextElement();
i++;
}
return a;
}
/**
* @inheritDoc
*/
public String[] listFilesystemRoots() {
String[] res = enumToStringArr(FileSystemRegistry.listRoots());
for(int iter = 0 ; iter < res.length ; iter++) {
res[iter] = "file:///" + res[iter];
}
return res;
}
private String[] enumToStringArr(Enumeration e) {
Vector v = new Vector();
while(e.hasMoreElements()) {
v.addElement(e.nextElement());
}
String[] response = new String[v.size()];
for(int iter = 0 ; iter < response.length ; iter++) {
response[iter] = (String)v.elementAt(iter);
}
return response;
}
/**
* @inheritDoc
*/
public String[] listFiles(String directory) throws IOException {
FileConnection fc = null;
try {
fc = (FileConnection)Connector.open(directory, Connector.READ);
return enumToStringArr(fc.list("*", true));
} finally {
cleanup(fc);
}
}
/**
* @inheritDoc
*/
public long getRootSizeBytes(String root) {
FileConnection fc = null;
try {
fc = (FileConnection)Connector.open(root, Connector.READ);
return fc.totalSize();
} catch(IOException err) {
err.printStackTrace();
return -1;
} finally {
cleanup(fc);
}
}
/**
* @inheritDoc
*/
public long getRootAvailableSpace(String root) {
FileConnection fc = null;
try {
fc = (FileConnection)Connector.open(root, Connector.READ);
return fc.availableSize();
} catch(IOException err) {
err.printStackTrace();
return -1;
} finally {
cleanup(fc);
}
}
/**
* @inheritDoc
*/
public void mkdir(String directory) {
FileConnection fc = null;
try {
fc = (FileConnection)Connector.open(directory, Connector.READ_WRITE);
fc.mkdir();
} catch(IOException err) {
err.printStackTrace();
} finally {
cleanup(fc);
}
}
/**
* @inheritDoc
*/
public void deleteFile(String file) {
FileConnection fc = null;
try {
fc = (FileConnection)Connector.open(file, Connector.WRITE);
fc.delete();
} catch(IOException err) {
err.printStackTrace();
} finally {
cleanup(fc);
}
}
/**
* @inheritDoc
*/
public boolean isHidden(String file) {
FileConnection fc = null;
try {
fc = (FileConnection)Connector.open(file, Connector.READ);
return fc.isHidden();
} catch(IOException err) {
err.printStackTrace();
return false;
} finally {
cleanup(fc);
}
}
/**
* @inheritDoc
*/
public void setHidden(String file, boolean h) {
FileConnection fc = null;
try {
fc = (FileConnection)Connector.open(file, Connector.READ_WRITE);
fc.setHidden(h);
} catch(IOException err) {
err.printStackTrace();
} finally {
cleanup(fc);
}
}
/**
* @inheritDoc
*/
public long getFileLength(String file) {
FileConnection fc = null;
try {
fc = (FileConnection)Connector.open(file, Connector.READ);
return fc.fileSize();
} catch(IOException err) {
err.printStackTrace();
return -1;
} finally {
cleanup(fc);
}
}
/**
* @inheritDoc
*/
public long getFileLastModified(String file) {
FileConnection fc = null;
try {
fc = (FileConnection) Connector.open(file, Connector.READ);
return fc.lastModified();
} catch (IOException err) {
err.printStackTrace();
return -1;
} finally {
cleanup(fc);
}
}
/**
* @inheritDoc
*/
public boolean isDirectory(String file) {
FileConnection fc = null;
try {
fc = (FileConnection)Connector.open(file, Connector.READ);
return fc.isDirectory();
} catch(IOException err) {
err.printStackTrace();
return false;
} finally {
cleanup(fc);
}
}
/**
* @inheritDoc
*/
public char getFileSystemSeparator() {
return '/';
}
/**
* @inheritDoc
*/
public boolean exists(String file) {
FileConnection fc = null;
try {
fc = (FileConnection)Connector.open(file, Connector.READ);
return fc.exists();
} catch(IOException err) {
return false;
} finally {
cleanup(fc);
}
}
/**
* @inheritDoc
*/
public void rename(String file, String newName) {
FileConnection fc = null;
try {
fc = (FileConnection)Connector.open(file, Connector.READ_WRITE);
fc.rename(newName);
} catch(IOException err) {
err.printStackTrace();
} finally {
cleanup(fc);
}
}
public void captureAudio(ActionListener response) {
captureResponse = response;
try {
final Form current = Display.getInstance().getCurrent();
final MMAPIPlayer player = MMAPIPlayer.createPlayer("capture://audio", null);
RecordControl record = (RecordControl) player.nativePlayer.getControl("RecordControl");
if (record == null) {
player.cleanup();
throw new RuntimeException("Capture Audio is not supported on this device");
}
final Form cam = new Form();
cam.setTransitionInAnimator(CommonTransitions.createEmpty());
cam.setTransitionOutAnimator(CommonTransitions.createEmpty());
cam.setLayout(new BorderLayout());
cam.show();
player.play();
final Label time = new Label("0:00");
cam.addComponent(BorderLayout.SOUTH, time);
cam.revalidate();
ActionListener l = new ActionListener() {
boolean recording = false;
OutputStream out = null;
String audioPath = null;
RecordControl record;
public void actionPerformed(ActionEvent evt) {
if(!recording){
record = (RecordControl) player.nativePlayer.getControl("RecordControl");
recording = true;
String type = record.getContentType();
String prefix = "";
if(type.endsWith("wav")){
prefix = ".wav";
}else if(type.endsWith("amr")){
prefix = ".amr";
}else if(type.endsWith("3gpp")){
prefix = ".3gp";
}
audioPath = getOutputMediaFile() + prefix;
try {
out = FileSystemStorage.getInstance().openOutputStream(audioPath);
record.setRecordStream(out);
record.startRecord();
cam.registerAnimated(new Animation() {
long current = System.currentTimeMillis();
long zero = current;
int sec = 0;
public boolean animate() {
long now = System.currentTimeMillis();
if(now - current > 1000){
current = now;
sec++;
return true;
}
return false;
}
public void paint(Graphics g) {
String txt = sec/60 + ":" + sec%60 ;
time.setText(txt);
}
});
} catch (IOException ex) {
ex.printStackTrace();
System.out.println("failed to store audio to " + audioPath );
}finally{
}
}else{
if(out != null){
try {
record.stopRecord();
record.commit();
out.close();
player.cleanup();
} catch (Exception ex) {
ex.printStackTrace();
}
}
captureResponse.actionPerformed(new ActionEvent(audioPath));
current.showBack();
}
}
};
cam.addGameKeyListener(Display.GAME_FIRE, l);
cam.addPointerReleasedListener(l);
} catch (IOException ex) {
ex.printStackTrace();
throw new RuntimeException("failed to start camera");
}
}
public void capturePhoto(ActionListener response) {
captureResponse = response;
final Form current = Display.getInstance().getCurrent();
final Form cam = new Form();
cam.setScrollable(false);
cam.setTransitionInAnimator(CommonTransitions.createEmpty());
cam.setTransitionOutAnimator(CommonTransitions.createEmpty());
cam.setLayout(new BorderLayout());
cam.show();
String platform = System.getProperty("microedition.platform");
MMAPIPlayer p = null;
if (platform != null && platform.indexOf("Nokia") >= 0) {
try {
p = MMAPIPlayer.createPlayer("capture://image", null);
} catch (Throwable e) {
// Ignore all exceptions for image capture, continue with video capture...
}
}
if (p == null) {
try {
p = MMAPIPlayer.createPlayer("capture://video", null);
} catch (Exception e) {
// The Nokia 2630 throws this if image/video capture is not supported
throw new RuntimeException("Image/video capture not supported on this phone");
}
}
final MMAPIPlayer player = p;
MIDPVideoComponent video = new MIDPVideoComponent(player, canvas);
video.play();
video.setVisible(true);
cam.addCommand(new com.codename1.ui.Command("Cancel"){
public void actionPerformed(ActionEvent evt) {
if(player != null){
player.cleanup();
}
captureResponse.actionPerformed(null);
current.showBack();
}
});
final ActionListener l = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
try {
cam.removeAll();
VideoControl cnt = (VideoControl) player.nativePlayer.getControl("VideoControl");
byte[] pic = cnt.getSnapshot("encoding=jpeg&width="+current.getWidth()+"&height=" + current.getHeight());
String imagePath = getOutputMediaFile() + ".jpg";
OutputStream out = null;
try {
if(pic != null){
out = FileSystemStorage.getInstance().openOutputStream(imagePath);
out.write(pic);
}
} catch (Throwable ex) {
ex.printStackTrace();
System.out.println("failed to store picture to " + imagePath);
} finally {
try {
if (out != null) {
out.close();
}
player.cleanup();
} catch (Throwable ex) {
ex.printStackTrace();
}
}
captureResponse.actionPerformed(new ActionEvent(imagePath));
current.showBack();
} catch (Throwable ex) {
ex.printStackTrace();
System.out.println("failed to take picture");
current.showBack();
}
}
};
cam.addGameKeyListener(Display.GAME_FIRE, l);
Container cn = new Container(new BorderLayout()){
public void pointerReleased(int x, int y) {
l.actionPerformed(null);
}
};
cn.setFocusable(true);
cn.addComponent(BorderLayout.CENTER, video);
cam.addComponent(BorderLayout.CENTER, cn);
cam.revalidate();
//cam.addPointerReleasedListener(l);
}
public void captureVideo(ActionListener response) {
captureResponse = response;
try {
final Form current = Display.getInstance().getCurrent();
final MMAPIPlayer player = MMAPIPlayer.createPlayer("capture://video", null);
RecordControl record = (RecordControl) player.nativePlayer.getControl("RecordControl");
if (record == null) {
player.cleanup();
throw new RuntimeException("Capture Video is not supported on this device");
}
final Form cam = new Form();
cam.setTransitionInAnimator(CommonTransitions.createEmpty());
cam.setTransitionOutAnimator(CommonTransitions.createEmpty());
cam.setLayout(new BorderLayout());
cam.show();
MIDPVideoComponent video = new MIDPVideoComponent(player, canvas);
video.play();
video.setVisible(true);
cam.addComponent(BorderLayout.CENTER, video);
final Label time = new Label("0:00");
cam.addComponent(BorderLayout.SOUTH, time);
cam.revalidate();
ActionListener l = new ActionListener() {
boolean recording = false;
OutputStream out = null;
String videoPath = null;
RecordControl record;
public void actionPerformed(ActionEvent evt) {
if(!recording){
record = (RecordControl) player.nativePlayer.getControl("RecordControl");
recording = true;
String type = record.getContentType();
String prefix = "";
if(type.endsWith("mpeg")){
prefix = ".mpeg";
}else if(type.endsWith("4")){
prefix = ".mp4";
}else if(type.endsWith("3gpp")){
prefix = ".3gp";
}else if(type.endsWith("avi")){
prefix = ".avi";
}
videoPath = getOutputMediaFile() + prefix;
try {
out = FileSystemStorage.getInstance().openOutputStream(videoPath);
record.setRecordStream(out);
record.startRecord();
cam.registerAnimated(new Animation() {
long current = System.currentTimeMillis();
long zero = current;
int sec = 0;
public boolean animate() {
long now = System.currentTimeMillis();
if(now - current > 1000){
current = now;
sec++;
return true;
}
return false;
}
public void paint(Graphics g) {
String txt = sec/60 + ":" + sec%60 ;
time.setText(txt);
}
});
} catch (IOException ex) {
ex.printStackTrace();
System.out.println("failed to store video to " + videoPath );
}finally{
}
}else{
if(out != null){
try {
record.stopRecord();
record.commit();
out.close();
player.cleanup();
} catch (Exception ex) {
ex.printStackTrace();
}
}
captureResponse.actionPerformed(new ActionEvent(videoPath));
current.showBack();
}
}
};
cam.addGameKeyListener(Display.GAME_FIRE, l);
cam.addPointerReleasedListener(l);
} catch (IOException ex) {
ex.printStackTrace();
throw new RuntimeException("failed to start camera");
}
}
/** Create a File for saving an image or video */
private String getOutputMediaFile() {
String dir = System.getProperty("fileconn.dir.private");
if(dir == null){
dir = FileSystemStorage.getInstance().getRoots()[0];
}
char separatpor = FileSystemStorage.getInstance().getFileSystemSeparator();
if(dir.endsWith("" + separatpor)){
return dir + System.currentTimeMillis();
}else{
return dir + separatpor + System.currentTimeMillis();
}
}
public void sendMessage(String[] recieptents, String subject, Message msg) {
String mailto = "mailto:" + recieptents[0];
for(int iter = 1 ; iter < recieptents.length ; iter++) {
mailto += "," + recieptents[iter];
}
mailto += "?body=" + Util.encodeUrl(msg.getContent()) + "&subject=" + Util.encodeUrl(subject);
execute(mailto);
}
/**
* @inheritDoc
*/
public void dial(String phoneNumber) {
execute("tel:" + phoneNumber);
}
/**
* @inheritDoc
*/
public void sendSMS(final String phoneNumber, final String message) throws IOException{
String address = "sms://" + phoneNumber;
MessageConnection con = null;
try {
con = (MessageConnection) Connector.open(address);
TextMessage txtmessage =
(TextMessage) con.newMessage(MessageConnection.TEXT_MESSAGE);
txtmessage.setAddress(address);
txtmessage.setPayloadText(message);
con.send(txtmessage);
} catch (Exception e) {
throw new IOException("failed to send sms " + e.getMessage());
} finally {
if (con != null) {
try {
con.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
}
/**
* @inheritDoc
*/
public String getPlatformName() {
return "me";
}
/**
* @inheritDoc
*/
public String[] getPlatformOverrides() {
return new String[] {"phone", "me"};
}
/**
* @inheritDoc
*/
public boolean hasNativeTheme() {
InputStream i = getResourceAsStream(getClass(), "/nokia_asha_theme.res");
try {
if(i != null) {
i.close();
return true;
}
} catch (IOException ex) {
}
i = getResourceAsStream(getClass(), "/nokia_touch_theme.res");
try {
if(i != null) {
i.close();
return true;
}
} catch (IOException ex) {
}
i = getResourceAsStream(getClass(), "/nokia_non_touch.res");
try {
if(i != null) {
i.close();
return true;
}
} catch (IOException ex) {
}
i = getResourceAsStream(getClass(), "/nativeJ2METheme.res");
try {
if(i != null) {
i.close();
return true;
}
} catch (IOException ex) {
}
return false;
}
/**
* @inheritDoc
*/
public void installNativeTheme() {
InputStream i = getResourceAsStream(getClass(), "/nokia_touch_theme.res");
if(i == null){
i = getResourceAsStream(getClass(), "/nokia_non_touch.res");
}
if(i == null){
i = getResourceAsStream(getClass(), "/nokia_asha_theme.res");
}
if(i == null){
i = getResourceAsStream(getClass(), "/nativeJ2METheme.res");
}
if(i != null){
try {
Resources r = Resources.open(i);
UIManager.getInstance().setThemeProps(r.getTheme(r.getThemeResourceNames()[0]));
} catch(Throwable t) {
t.printStackTrace();
}
}
}
/**
* @inheritDoc
*/
public String [] getAllContacts(boolean withNumbers) {
return MIDPContactsManager.getInstance().getAllContacts(withNumbers);
}
/**
* @inheritDoc
*/
public Contact getContactById(String id){
return MIDPContactsManager.getInstance().getContactById(id);
}
/**
* @inheritDoc
*/
public Contact getContactById(String id, boolean includesFullName, boolean includesPicture,
boolean includesNumbers, boolean includesEmail, boolean includeAddress){
return MIDPContactsManager.getInstance().getContactById(id, includesFullName, includesPicture,
includesNumbers, includesEmail, includeAddress);
}
public String createContact(String firstName, String surname, String officePhone, String homePhone, String cellPhone, String email) {
return MIDPContactsManager.getInstance().createContact(firstName, surname, officePhone, homePhone, cellPhone, email);
}
public boolean deleteContact(String id) {
return MIDPContactsManager.getInstance().deleteContact(id);
}
/**
* @inheritDoc
*/
public Media createMediaRecorder(String path, String mimeType) throws IOException {
return new MediaRecorder(path);
}
private L10NManager lm;
/**
* @inheritDoc
*/
public L10NManager getLocalizationManager() {
if(lm == null) {
String l = System.getProperty("microedition.locale");
String lang = "en";
String country = "US";
if(l != null && l.length() >= 5) {
lang = l.substring(0, 2);
country = l.substring(3, 5);
}
lm = new L10NManager(lang, country) {
public String format(int number) {
return super.format(number);
}
public String format(double number) {
return super.format(number);
}
public String formatCurrency(double currency) {
return super.formatCurrency(currency);
}
public String formatDateLongStyle(Date d) {
return super.formatDateLongStyle(d);
}
public String formatDateShortStyle(Date d) {
return super.formatDateShortStyle(d);
}
public String formatDateTime(Date d) {
return super.formatDateTime(d);
}
public String getCurrencySymbol() {
return super.getCurrencySymbol();
}
};
}
return lm;
}
/**
* Returns the native implementation of the code scanner or null
*
* @return code scanner instance
*/
public CodeScanner getCodeScanner() {
try {
return new ScannerHider().getCodeScanner(canvas);
} catch(Throwable t) {
return null;
}
}
public boolean hasCamera() {
String capture = System.getProperty("supports.video.capture");
return "true".equals(capture);
}
}