/*
* Copyright 2013 Elina Vartiainen and Simon Robinson
*
* This file is part of Com-Me.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ac.robinson.mediaphonejavame.form;
import java.io.OutputStream;
import javax.microedition.io.Connector;
import javax.microedition.io.file.FileConnection;
import javax.microedition.media.Manager;
import javax.microedition.media.MediaException;
import javax.microedition.media.Player;
import javax.microedition.media.control.VideoControl;
import ac.robinson.mediaphonejavame.MediaPhone;
import ac.robinson.mediaphonejavame.localization.L10nConstants;
import ac.robinson.mediaphonejavame.util.ImageCacheUtilities;
import com.sun.lwuit.Command;
import com.sun.lwuit.Form;
import com.sun.lwuit.Image;
import com.sun.lwuit.Label;
import com.sun.lwuit.MediaComponent;
import com.sun.lwuit.TextArea;
import com.sun.lwuit.events.ActionEvent;
import com.sun.lwuit.events.ActionListener;
import com.sun.lwuit.layouts.BorderLayout;
/**
* Captures and saves a photo using the phone's camera and viewfinder.
*/
class CameraForm extends Form implements ActionListener {
private FrameEditorForm mFrameEditorForm;
private Player mCapturePlayer;
private VideoControl mVideoControl;
private MediaComponent mMediaComponent;
private byte[] mCameraOutput = null;
private Label mImagePreview = null;
private TextArea mStatusText;
// TODO: load previous photo here, allow selecting image from gallery, and allow deletion
public CameraForm(FrameEditorForm frameEditorForm) {
super(MediaPhone.getString(L10nConstants.keys.TITLE_CAMERA));
mFrameEditorForm = frameEditorForm;
setLayout(new BorderLayout());
setScrollable(false);
mStatusText = new TextArea(MediaPhone.getString(L10nConstants.keys.HINT_LOADING));
mStatusText.setEditable(false);
addComponent(BorderLayout.CENTER, mStatusText);
addCommand(new Command(MediaPhone.getString(L10nConstants.keys.BUTTON_CANCEL),
MediaPhone.id.button_cancel_picture));
addCommandListener(this);
initialiseCamera();
}
private void initialiseCamera() {
try {
// for a non-deprecated alternative, see: http://stackoverflow.com/questions/7742397
// or: http://stackoverflow.com/questions/8652269
try {
mCapturePlayer = Manager.createPlayer("capture://image");
mCapturePlayer.realize();
} catch (Exception e) {
mCapturePlayer = Manager.createPlayer("capture://video");
mCapturePlayer.realize();
}
mVideoControl = (VideoControl) (mCapturePlayer.getControl("VideoControl"));
if (mVideoControl != null) {
mMediaComponent = new MediaComponent(mCapturePlayer);
mMediaComponent.setFocusable(false);
addComponent(BorderLayout.CENTER, mMediaComponent);
addCommand(new Command(MediaPhone.getString(L10nConstants.keys.BUTTON_CAPTURE),
MediaPhone.id.button_take_picture));
mCapturePlayer.start();
mStatusText.setText("");
} else {
mStatusText.setText(MediaPhone.getString(L10nConstants.keys.ERROR_CAMERA_NOT_SUPPORTED));
}
} catch (Exception e) {
mStatusText.setText(MediaPhone.getString(L10nConstants.keys.ERROR_CAMERA_NOT_SUPPORTED));
}
}
public void actionPerformed(ActionEvent event) {
switch (event.getCommand().getId()) {
case MediaPhone.id.button_take_picture:
capturePhoto();
break;
case MediaPhone.id.button_save_picture:
String imagePath = savePicture();
ImageCacheUtilities.cacheImage(imagePath, mImagePreview.getIcon()); // saves a file permissions prompt
mFrameEditorForm.setCurrentImage(imagePath);
mImagePreview = null;
mCameraOutput = null;
mCapturePlayer.close();
mCapturePlayer = null;
mVideoControl = null;
mMediaComponent = null;
mFrameEditorForm.show();
break;
case MediaPhone.id.button_cancel_picture:
if (mCapturePlayer != null) {
mCapturePlayer.close();
mCapturePlayer = null;
mVideoControl = null;
mMediaComponent = null;
}
mFrameEditorForm.show();
break;
case MediaPhone.id.button_retake_picture:
removeComponent(mImagePreview);
mImagePreview = null;
mCameraOutput = null;
addComponent(BorderLayout.CENTER, mMediaComponent);
removeAllCommands();
addCommand(new Command(MediaPhone.getString(L10nConstants.keys.BUTTON_CANCEL),
MediaPhone.id.button_cancel_picture));
addCommand(new Command(MediaPhone.getString(L10nConstants.keys.BUTTON_CAPTURE),
MediaPhone.id.button_take_picture));
try {
mCapturePlayer.start();
} catch (MediaException e) {
e.printStackTrace();
}
mStatusText.setText("");
break;
}
}
private void capturePhoto() {
try {
// TODO: use thread here to speed up?
try {
// if we have a capture command, we know videoControl is not null
mCameraOutput = mVideoControl.getSnapshot("encoding=jpeg&width=320&height=240");
} catch (Exception e) {
mCameraOutput = mVideoControl.getSnapshot(null);
}
mCapturePlayer.stop();
removeComponent(mMediaComponent);
mImagePreview = new Label(Image.createImage(mCameraOutput, 0, mCameraOutput.length));
addComponent(BorderLayout.CENTER, mImagePreview);
removeAllCommands();
addCommand(new Command(MediaPhone.getString(L10nConstants.keys.BUTTON_RETAKE),
MediaPhone.id.button_retake_picture));
addCommand(new Command(MediaPhone.getString(L10nConstants.keys.BUTTON_SAVE),
MediaPhone.id.button_save_picture));
} catch (MediaException e) {
mStatusText.setText(MediaPhone.getString(L10nConstants.keys.ERROR_TAKING_PHOTO));
if (MediaPhone.DEBUG) {
e.printStackTrace();
}
}
}
private String savePicture() {
String outputFile = MediaPhone.IMAGES_PATH + MediaPhone.getString(L10nConstants.keys.APP_NAME) + "-"
+ Integer.toHexString((int) System.currentTimeMillis() & 0xffffffff) + ".jpg";
FileConnection fileConnection = null;
OutputStream outputStream = null;
try {
String encodings = System.getProperty("video.snapshot.encodings");
if (encodings == null || encodings.indexOf("jpg") < 0) {
throw new Exception("JPEG encoding is not supported on this device");
}
fileConnection = (FileConnection) Connector.open(outputFile, Connector.READ_WRITE); // *must* be r/w
if (!fileConnection.exists()) {
fileConnection.create();
}
outputStream = fileConnection.openOutputStream();
outputStream.write(mCameraOutput);
mStatusText.setText(MediaPhone.getString(L10nConstants.keys.HINT_PHOTO_SAVED));
} catch (Exception e) {
mStatusText.setText(MediaPhone.getString(L10nConstants.keys.ERROR_SAVING_PHOTO));
if (MediaPhone.DEBUG) {
e.printStackTrace();
}
} finally {
try {
outputStream.close();
} catch (Exception e) {
}
try {
fileConnection.close();
} catch (Exception e) {
}
}
return outputFile;
}
}