/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.codename1.impl.blackberry.codescan;
import com.codename1.codescan.CodeScanner;
import com.codename1.codescan.ScanResult;
import com.codename1.media.Media;
import com.codename1.ui.Form;
import com.google.zxing.*;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.QRCodeReader;
import java.util.Hashtable;
import java.util.Timer;
import java.util.TimerTask;
import javax.microedition.media.Manager;
import javax.microedition.media.MediaException;
import javax.microedition.media.Player;
import javax.microedition.media.control.VideoControl;
import net.rim.device.api.system.Application;
import net.rim.device.api.system.Bitmap;
import net.rim.device.api.system.Display;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.container.MainScreen;
/**
*
* @author Chen
*/
public class CodeScannerImpl extends CodeScanner{
private MultimediaManager multimediaManager;
private ScanResult callback;
private boolean isQRScanning;
private VideoControl videoControl;
private Player player;
private Field viewFinder;
private ViewFinderScreen viewFinderScreen;
private BarcodeScanTask task;
private Timer timer;
private Result result;
public CodeScannerImpl(MultimediaManager multimediaManager) {
// Setup barcode decoding hints, arg passed is not used at present
this.multimediaManager = multimediaManager;
}
public void scanQRCode(ScanResult callback) {
this.callback = callback;
isQRScanning = true;
startScan();
}
public void scanBarCode(ScanResult callback) {
this.callback = callback;
isQRScanning = false;
startScan();
}
public void cancelScan() {
stopScan();
if (callback != null) {
callback.scanCanceled();
//callback.onEvent(doneEvent);
callback = null;
}
}
public void handleDecodedText(Result theResult) {
// And then stop the scan and go back to the LWUIT form,
// if there was no error. TODO: fix this properly later.
callback.scanCompleted(theResult.getText(), theResult.getBarcodeFormat().getName(), theResult.getRawBytes());
stopScan();
callback = null;
}
/**
* Get the player instance
*
* @return player instance
*/
public Player getPlayer() {
return player;
}
/**
* Get the video control
*
* @return video control instance
*/
public VideoControl getVideoControl() {
return videoControl;
}
public void startScan() {
try {
System.gc();
player = Manager.createPlayer("capture://video");
player.realize();
multimediaManager.setZoom(player);
multimediaManager.setExposure(player);
multimediaManager.setFlash(player);
player.start();
videoControl = (VideoControl) player.getControl("VideoControl");
viewFinder = (Field) videoControl.initDisplayMode(
VideoControl.USE_GUI_PRIMITIVE,
"net.rim.device.api.ui.Field");
if (videoControl != null) {
viewFinderScreen = new ViewFinderScreen();
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
UiApplication.getUiApplication().pushScreen(
viewFinderScreen);
viewFinder.setFocus();
}
});
videoControl.setVisible(true);
videoControl.setDisplayFullScreen(true);
task = new BarcodeScanTask();
// create timer every 3 seconds, get a screenshot
timer = new Timer();
timer.schedule(task, 0, 3000); // once every 3 seconds
} else {
throw new MediaException("Video Control is not initialized");
}
} catch (Exception e) {
callback.scanError(-1, e.getMessage());
}
}
public void stopScan() {
if (timer != null) {
timer.cancel(); // stop the timer
}
// Destroy the videoControl and player
if (videoControl != null) {
// TODO: This might not be needed, but have it just in case
videoControl.setVisible(false);
videoControl = null;
}
if (player != null) {
player.close();
player = null;
}
if (viewFinderScreen != null) {
synchronized (Application.getEventLock()) {
// viewFinderScreen.close();
UiApplication.getUiApplication().popScreen(viewFinderScreen);
}
viewFinderScreen = null;
}
System.gc();
}
final class BarcodeScanTask extends TimerTask {
public void run() {
try {
Bitmap bmpScreenshot = new Bitmap(Display.getWidth(),
Display.getHeight());
multimediaManager.setFocus(player);
Display.screenshot(bmpScreenshot);
// creating luminance source
LuminanceSource source = new BitmapLuminanceSource(
bmpScreenshot);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(
source));
if(isQRScanning){
QRCodeReader reader = new QRCodeReader();
result = reader.decodeQR(bitmap);
}else{
MultiFormatReader reader = new MultiFormatReader();
result = reader.decodeBarcode(bitmap);
}
handleDecodedText(result);
timer.cancel(); // stop the timer
} catch (Throwable e) {
callback.scanError(-1, e.getMessage());
}
}
}
public final class ViewFinderScreen extends MainScreen {
public ViewFinderScreen() throws Exception {
super(MainScreen.DEFAULT_CLOSE);
add(viewFinder);
}
protected boolean navigationClick(int arg0, int arg1) {
cancelScan();
this.close();
return true;
}
public boolean onClose() {
try {
stopScan();
return super.onClose();
} catch (Exception e) {
return false;
}
}
}
}