CameraScreen.java

/**
 * Copyright (c) 2012 Nokia Corporation. All rights reserved.
 * Nokia and Nokia Connecting People are registered trademarks of Nokia Corporation.
 * Oracle and Java are trademarks or registered trademarks of Oracle and/or its
 * affiliates. Other product and company names mentioned herein may be trademarks
 * or trade names of their respective owners.
 * See LICENSE.TXT for license information.
 */

package com.nokia.example.mmsmidlet;

import java.io.IOException;
import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Graphics;
import javax.microedition.media.Manager;
import javax.microedition.media.MediaException;
import javax.microedition.media.Player;
import javax.microedition.media.control.VideoControl;

import com.nokia.mid.ui.VirtualKeyboard;
import com.nokia.mid.ui.gestures.GestureEvent;
import com.nokia.mid.ui.gestures.GestureInteractiveZone;
import com.nokia.mid.ui.gestures.GestureListener;
import com.nokia.mid.ui.gestures.GestureRegistrationManager;
import com.nokia.mid.ui.orientation.Orientation;

// The CameraScreen class shows the live view
// of the camera using the MMAPI and gives
// commands to capture the contents of the camera
class CameraScreen extends Canvas implements CommandListener, GestureListener {

    private final MMSMIDlet midlet;
    private final Command exitCommand;
    private Player player = null;
    private Command captureCommand = null;
    private VideoControl videoControl = null;

    CameraScreen(MMSMIDlet midlet) {
        this.midlet = midlet;

        /**
         * To determine whether a Series 40 device is a full touch device
         */
        if (System.getProperty("com.nokia.keyboard.type").equals("None")) {
            /**
             * hide the open keypad command from the Options menu
             */
            VirtualKeyboard.hideOpenKeypadCommand(true);
        }

        // Builds the user interface
        exitCommand = new Command("Exit", Command.EXIT, 1);
        addCommand(exitCommand);
        captureCommand = new Command("Capture", Command.SCREEN, 1);
        addCommand(captureCommand);
        setCommandListener(this);

        Orientation.setAppOrientation(Orientation.ORIENTATION_PORTRAIT);

        initializeGesture();

    }

    // Paint the canvas' background in black
    public void paint(Graphics g) {
        // black background
        g.setColor(0x0000000);
        g.fillRect(0, 0, getWidth(), getHeight());
    }

    public void commandAction(Command c, Displayable d) {
        if (c == exitCommand) {
            midlet.exitApplication();
        } else if (c == captureCommand) {
            captureImage();
        }
    }

    public void keyPressed(int keyCode) {
        if (getGameAction(keyCode) == FIRE) {
            captureImage();
        }
    }

    private boolean checkEncodingSupport() {
        String encodings = System.getProperty("video.snapshot.encodings");
        return     (encodings != null) &&
            (encodings.indexOf("png") != -1) && (encodings.indexOf("image/bmp") != -1);
    }

    // Creates and starts the video player
    synchronized void start() {
        try {

            if (!checkEncodingSupport()) {
                player = Manager.createPlayer("capture://image");
            } else {
                player = Manager.createPlayer("capture://video");
            }

            player.realize();

            // Get VideoControl for the viewfinder
            videoControl = (VideoControl) player.getControl("VideoControl");
            if (videoControl == null) {
                discardPlayer(false);
                midlet.showError("Cannot get the video control.\n"
                        + "Capture may not be supported.");
                player = null;
            } else {
                // Set up the viewfinder on the screen.
                videoControl.initDisplayMode(VideoControl.USE_DIRECT_VIDEO,
                        this);

                int canvasWidth = getWidth();
                int canvasHeight = getHeight();

                videoControl.setDisplaySize(canvasWidth, canvasHeight);

                int displayWidth = videoControl.getDisplayWidth();
                int displayHeight = videoControl.getDisplayHeight();
                int x = (canvasWidth - displayWidth) / 2;
                int y = (canvasHeight - displayHeight) / 2;
                videoControl.setDisplayLocation(x, y);

                player.start();
                videoControl.setVisible(true);
            }
        } catch (IOException ioe) {
            discardPlayer(false);
            midlet.showError("IOException: " + ioe.getMessage());
        } catch (MediaException me) {
            midlet.showError("MediaException: " + me.getMessage());
        } catch (SecurityException se) {
            midlet.showError("SecurityException: " + se.getMessage());
        }
    }

    // Stops the video player
    synchronized void stop() {
        if (player != null) {
            try {
                videoControl.setVisible(false);
                player.stop();
            } catch (MediaException me) {
                midlet.showError("MediaException: " + me.getMessage());
            }
        }
    }

    // this method will discard the video player
    private void discardPlayer(boolean restart) {
        if (player != null) {
            player.deallocate();
            player.close();
            player = null;
        }
        videoControl = null;

        if (restart) {
            start();
        }
    }

    // captures the image from the video player
    // in a separate thread
    private void captureImage() {
        if (player != null) {
            // Capture image in a new thread.
            new Thread() {

                public void run() {
                    try {
                        byte[] jpgImage
                            = videoControl.getSnapshot("encoding=image/jpg&width=270&height=360");
                        midlet.imageCaptured(jpgImage);
                        discardPlayer(false);
                    } catch (MediaException me) {
                        try {
                            //For Devices that do not support jpg image encoding, mostly Series 40
                            byte[] jpgImage = videoControl.getSnapshot(null);
                            midlet.imageCaptured(jpgImage);
                            discardPlayer(false);
                        } catch (Exception e) {
                            midlet.showError("Exception: " + e.getMessage());
                            discardPlayer(true);
                        }
                    } catch (SecurityException se) {
                        midlet.showError("SecurityException: "
                                + se.getMessage());
                    }
                }
            }.start();
        }
    }

    public void initializeGesture() {
        GestureRegistrationManager.setListener(this, this);

        // Create an interactive zone and set it to receive taps
        GestureInteractiveZone myGestureZone
            = new GestureInteractiveZone(GestureInteractiveZone.GESTURE_TAP);

        // Set the location (relative to the container) and size of the interactive zone:
        myGestureZone.setRectangle(0, 0, getWidth(), getHeight());

        // Register the interactive zone for GestureCanvas (this)
        GestureRegistrationManager.register(this, myGestureZone);
    }

    public void gestureAction(Object c, GestureInteractiveZone giz, GestureEvent gestureEvent) {
        switch (gestureEvent.getType()) {

            case GestureInteractiveZone.GESTURE_TAP:
                captureImage();

                break;
        }
    }
}