/*
* Copyright 1990-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
*
* This program 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.
*
* This program 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 at /legal/license.txt).
*
* 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 Sun Microsystems, Inc., 4150 Network Circle, Santa
* Clara, CA 95054 or visit www.sun.com if you need additional
* information or have any questions.
*/
package com.sun.amms.directcontrol;
import com.sun.amms.AMMSMPEventListener;
import com.sun.mmedia.DirectCamera;
import java.io.IOException;
import java.io.InterruptedIOException;
import javax.microedition.amms.control.camera.*;
import javax.microedition.media.MediaException;
import javax.microedition.media.Player;
import javax.microedition.media.PlayerListener;
import com.sun.j2me.app.AppPackage;
import com.sun.j2me.security.MMAPIPermission;
public class DirectSnapshotControl extends CameraDependentControl
implements SnapshotControl, PlayerListener {
private AMMSMPEventListener _mp_listener;
private Jsr75DirCheckerProxy _dir_checker;
private String _directory;
private String _prefix;
private String _suffix;
private String tmp_directory;
private String tmp_prefix;
private String tmp_suffix;
private Object stateLock = new Object();
private final int STATE_IDLE = 0;
private final int STATE_SHOOTING = 1;
private int state = STATE_IDLE;
public static DirectSnapshotControl createInstance(DirectCamera cam) {
if (!nIsSupported(cam.getNativeHandle())) {
return null;
}
return new DirectSnapshotControl(cam);
}
private DirectSnapshotControl(DirectCamera cam) {
_mp_listener = AMMSMPEventListener.getInstance();
setCamera(cam);
cam.addPlayerListener( this );
String def_loc = System.getProperty( "fileconn.dir.photos" );
// remove prefix
if( def_loc.startsWith( "file:" ) ) {
def_loc = def_loc.substring( "file:".length() );
}
// leave only one leading slash
while( def_loc.startsWith( "//" ) ) {
def_loc = def_loc.substring( 1 );
}
// force ending slash
if( 0 == def_loc.length() || def_loc.charAt( def_loc.length() - 1 ) != '/' ) {
def_loc += "/";
}
tmp_directory = def_loc;
if( isCameraAccessible() ) {
nSetDirectory( getNativeHandle(), def_loc );
_directory = def_loc;
}
}
private synchronized Jsr75DirCheckerProxy get75DirChecker() {
if (_dir_checker == null) {
Class c = null;
try {
c = Class.forName(
"com.sun.amms.directcontrol.Jsr75DirCheckerProxyImpl");
_dir_checker = (Jsr75DirCheckerProxy)c.newInstance();
} catch (ClassNotFoundException e1) {
} catch (IllegalAccessException e2) {
throw new RuntimeException(
"Could not access the class" + c.toString());
} catch (InstantiationException e3) {
throw new RuntimeException(
"Could not instantiate the class" + c.toString());
}
if (_dir_checker == null) {
try {
c = Class.forName(
"com.sun.amms.directcontrol.Jsr75DirCheckerProxyStub");
_dir_checker = (Jsr75DirCheckerProxy)c.newInstance();
} catch (ClassNotFoundException e1) {
throw new RuntimeException(
"Could not find DirChecker class");
} catch (IllegalAccessException e2) {
throw new RuntimeException(
"Could not access the class" + c.toString());
} catch (InstantiationException e3) {
throw new RuntimeException(
"Could not instantiate the class" + c.toString());
}
}
}
return _dir_checker;
}
public void playerUpdate( Player player, java.lang.String event,
java.lang.Object eventData ) {
if( SHOOTING_STOPPED.equals( event ) || STORAGE_ERROR.equals( event ) ) {
synchronized( stateLock ) {
state = STATE_IDLE;
if( !tmp_directory.equals(_directory) ) {
setDirectory( tmp_directory );
}
if( !tmp_prefix.equals( _prefix ) ) {
setFilePrefix( tmp_prefix );
}
if( !tmp_suffix.equals( _suffix ) ) {
setFileSuffix( tmp_suffix );
}
}
}
}
/**
* Sets the file directory where the images will be stored.
* <p>
* The directory name is given as a String which can contain the trailing
* slash "/" in the directory name but it is not required.
* </p>
* <p>
* For example, both
* <code>"/SDCard/"</code> and <code>"/SDCard"</code>
* set the directory to the root of the SDCard in a platform
* implementing <code>FileConnection</code> of JSR-75.
* In case of <code>FileConnection</code> of JSR-75 the return
* value of <code>FileConnection.getPath()</code> can be used
* as it is as a parameter for this method.
* </p>
* @param directory the storage directory.
* @throws IllegalArgumentException if the given directory does not exist
* or it is null.
* @throws SecurityException if the creation of files to the given location
* is not allowed.
*/
public void setDirectory(String directory) {
if (null == directory) {
throw new IllegalArgumentException("null passed to setDirectory");
}
try {
get75DirChecker();
} catch (Throwable t) {
}
if (_dir_checker != null) {
try {
_dir_checker.checkDirectory(directory);
} catch (IOException e) {
throw new SecurityException(
"IOException was thrown while checking Camera Snapshot " +
"directory security permissions: " + e.getMessage());
}
}
String dir = "" + directory;
if (0 == dir.length() || dir.charAt(dir.length() - 1) != '/') dir += "/";
if (isCameraAccessible())
{
synchronized( stateLock ) {
tmp_directory = dir;
if( STATE_IDLE == state ) {
nSetDirectory( getNativeHandle(), dir );
_directory = dir;
}
}
}
}
/**
* Gets the storage directory. If <code>setDirectory</code> has not been
* called the directory
* points to the default image storing location.
*
* @return The current storage directory with the trailing slash "/".
*/
public String getDirectory() {
return tmp_directory;
}
/**
* Sets the filename prefix.
* @param prefix The prefix String for the files to be created.
* @throws IllegalArgumentException if the given prefix cannot be set or if
* it is null.
*/
public void setFilePrefix(String prefix) {
if (null == prefix) {
throw new IllegalArgumentException("null passed to setFilePrefix!");
}
if (isCameraAccessible()) {
synchronized( stateLock ) {
tmp_prefix = prefix;
if( STATE_IDLE == state ) {
nSetFilePrefix(getNativeHandle(), prefix);
_prefix = prefix;
}
}
}
}
/**
* Gets the filename prefix.
*
* @return The filename prefix.
*/
public String getFilePrefix() {
return tmp_prefix;
}
/**
* Sets the filename suffix.
*
* @throws IllegalArgumentException if the given suffix cannot be set or if
* it is null.
*/
public void setFileSuffix(String suffix) {
if (null == suffix) {
throw new IllegalArgumentException("null passed to setFileSuffix!");
}
if (isCameraAccessible()) {
synchronized( stateLock ) {
tmp_suffix = suffix;
if( STATE_IDLE == state ) {
nSetFileSuffix(getNativeHandle(), suffix);
_suffix = suffix;
}
}
}
}
/**
* Gets the filename suffix.
*
* @return The filename suffix.
*/
public String getFileSuffix() {
return tmp_suffix;
}
/**
* Starts burst shooting.
*
* @param maxShots Maximum number of shots that are going to be taken
* or FREEZE or FREEZE_AND_CONFIRM. Integer.MAX_VALUE
* will take as many shots as possible.
*
* @throws IllegalArgumentException if maxShots is less than one.
* @throws IllegalStateException if prefix and suffix have not been set.
* @throws SecurityException if the application does not have permission to
* take snapshots.
*/
public void start(int maxShots) throws SecurityException {
checkPermission();
if (_prefix == null && _suffix == null) {
throw new IllegalStateException(
"Both prefix and suffix are not set!");
}
if (!isCameraStarted()) {
throw new IllegalStateException("Camera is not started!");
}
if ((maxShots < 1) && (maxShots != FREEZE) &&
(maxShots != FREEZE_AND_CONFIRM )) {
throw new IllegalArgumentException("maxShots " + maxShots +
" is invalid!");
}
if (isCameraAccessible()) {
getCamera().checkSnapshotPermission();
synchronized( stateLock ) {
nStart( getNativeHandle(), maxShots );
state = STATE_SHOOTING;
}
if (FREEZE_AND_CONFIRM == maxShots) {
getCamera().sendEvent(WAITING_UNFREEZE, null);
}
}
}
private static void checkPermission() {
try {
AppPackage.getInstance().
checkForPermission(MMAPIPermission.SNAPSHOT);
} catch (InterruptedException ie) {
throw new SecurityException(
"Interrupted while trying to ask the user permission");
}
}
/**
* Stops burst shooting.
*/
public void stop() {
if( isCameraAccessible() ) {
nStop(getNativeHandle());
}
}
/**
* Unfreezes the viewfinder and saves the snapshot depending
* on the parameter. The method does not do anything if
* <code>start(FREEZE_AND_CONFIRM)</code> has not been called.
*
* @param save true=saves the snapshot, false=does not save the snapshot.
*/
public void unfreeze(boolean save) {
if( isCameraAccessible() ) {
synchronized( stateLock ) {
nUnfreeze(getNativeHandle(), save);
state = STATE_IDLE;
}
}
}
protected native void nSetDirectory(int hNative, String directory);
protected native String nGetDirectory(int hNative);
protected native void nSetFilePrefix(int hNative, String prefix);
protected native String nGetFilePrefix(int hNative);
protected native void nSetFileSuffix(int hNative, String suffix);
protected native String nGetFileSuffix(int hNative);
protected native void nStart(int hNative, int maxShots);
protected native void nStop(int hNative);
protected native void nUnfreeze(int hNative, boolean save);
protected static native boolean nIsSupported(int hNative);
}