Return-Path: X-Original-To: apmail-cordova-commits-archive@www.apache.org Delivered-To: apmail-cordova-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 22681F153 for ; Fri, 5 Jul 2013 12:48:13 +0000 (UTC) Received: (qmail 16413 invoked by uid 500); 5 Jul 2013 12:47:58 -0000 Delivered-To: apmail-cordova-commits-archive@cordova.apache.org Received: (qmail 16278 invoked by uid 500); 5 Jul 2013 12:47:58 -0000 Mailing-List: contact commits-help@cordova.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cordova.apache.org Delivered-To: mailing list commits@cordova.apache.org Received: (qmail 14217 invoked by uid 99); 5 Jul 2013 12:47:43 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 05 Jul 2013 12:47:43 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id DFEA082C463; Fri, 5 Jul 2013 12:47:42 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: agrieve@apache.org To: commits@cordova.apache.org Date: Fri, 05 Jul 2013 12:48:07 -0000 Message-Id: <8e70dbfe443c493091f2f1425716572c@git.apache.org> In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [26/51] [partial] Merge master2->master http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/ac0c95be/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/camera/Camera.java ---------------------------------------------------------------------- diff --git a/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/camera/Camera.java b/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/camera/Camera.java deleted file mode 100644 index d54483f..0000000 --- a/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/camera/Camera.java +++ /dev/null @@ -1,470 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.cordova.camera; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.Date; - -import javax.microedition.io.Connector; -import javax.microedition.io.file.FileConnection; - -import org.apache.cordova.api.Plugin; -import org.apache.cordova.api.PluginResult; -import org.apache.cordova.json4j.JSONArray; -import org.apache.cordova.json4j.JSONException; -import org.apache.cordova.util.Logger; - -import net.rim.blackberry.api.invoke.CameraArguments; -import net.rim.blackberry.api.invoke.Invoke; -import net.rim.device.api.io.Base64OutputStream; -import net.rim.device.api.io.IOUtilities; -import net.rim.device.api.system.ApplicationDescriptor; -import net.rim.device.api.system.Bitmap; -import net.rim.device.api.system.Characters; -import net.rim.device.api.system.ControlledAccessException; -import net.rim.device.api.system.EncodedImage; -import net.rim.device.api.system.EventInjector; -import net.rim.device.api.system.JPEGEncodedImage; -import net.rim.device.api.system.PNGEncodedImage; -import net.rim.device.api.ui.UiApplication; - -/** - * The Camera plugin interface. - * - * The Camera class can invoke the following actions: - * - * - takePicture: takes photo and returns base64 encoded image or image file URI - * - * future? - * - captureVideo... - * - */ -public class Camera extends Plugin -{ - /** - * Possible actions. - */ - public static final String ACTION_TAKE_PICTURE = "takePicture"; - - /** - * Maximum image encoding size (in bytes) to allow. (Obtained unofficially - * through trial and error). Anything larger will cause stability issues - * when sending back to the browser. - */ - private static final long MAX_ENCODING_SIZE = 1500000L; - - /** - * Executes the requested action and returns a PluginResult. - * - * @param action The action to execute. - * @param callbackId The callback ID to be invoked upon action completion - * @param args JSONArry of arguments for the action. - * @return A PluginResult object with a status and message. - */ - public PluginResult execute(String action, JSONArray args, String callbackId) - { - PluginResult result = null; - - // take a picture - if (action != null && action.equals(ACTION_TAKE_PICTURE)) - { - // Parse the options specified for the take picture action. - CameraOptions options; - try { - options = CameraOptions.fromJSONArray(args); - } catch (NumberFormatException e) { - return new PluginResult(PluginResult.Status.JSON_EXCEPTION, "One of the camera options is not a valid number."); - } catch (JSONException e) { - return new PluginResult(PluginResult.Status.JSON_EXCEPTION, "One of the camera options is not valid JSON."); - } - - // launch native camera application - launchCamera(new PhotoListener(options, callbackId)); - - // The native camera application runs in a separate process, so we - // must now wait for the listener to retrieve the photo taken. - // Return NO_RESULT status so plugin manager does not invoke a callback, - // but keep the callback so the listener can invoke it later. - result = new PluginResult(PluginResult.Status.NO_RESULT); - result.setKeepCallback(true); - return result; - } - else - { - result = new PluginResult(PluginResult.Status.INVALID_ACTION, "Camera: Invalid action:" + action); - } - - return result; - } - - /** - * Launches the native camera application. - */ - private static void launchCamera(PhotoListener listener) - { - // MMAPI interface doesn't use the native Camera application or interface - // (we would have to replicate it). So, we invoke the native Camera application, - // which doesn't allow us to set any options. - synchronized(UiApplication.getEventLock()) { - UiApplication.getUiApplication().addFileSystemJournalListener(listener); - Invoke.invokeApplication(Invoke.APP_TYPE_CAMERA, new CameraArguments()); - } - } - - /** - * Closes the native camera application. - */ - public static void closeCamera() - { - // simulate two escape characters to exit native camera application - // no, there is no other way to do this - UiApplication.getUiApplication().invokeLater(new Runnable() { - public void run() { - try - { - EventInjector.KeyEvent inject = new EventInjector.KeyEvent( - EventInjector.KeyEvent.KEY_DOWN, Characters.ESCAPE, 0); - inject.post(); - inject.post(); - } - catch (ControlledAccessException e) - { - // the application doesn't have key injection permissions - Logger.log(Camera.class.getName() + ": Unable to close camera. " + - ApplicationDescriptor.currentApplicationDescriptor().getName() + - " does not have key injection permissions."); - } - } - }); - } - - /** - * Returns the image file URI or the Base64-encoded image. - * @param filePath The full path of the image file - * @param options Specifies the format of the image and the result - * @param callbackId The id of the callback to receive the result - */ - public static void processImage(String filePath, CameraOptions options, - String callbackId) { - PluginResult result = null; - try - { - // wait for the file to be fully written to the file system - // to avoid premature access to it (yes, this has happened) - waitForImageFile(filePath); - - // Reformat the image if the specified options require it, - // otherwise, get encoded string if base 64 string is output format. - String imageURIorData = filePath; - - // save to file:///store/home/user/ as oppsed to photo album - // so it doesn't show up in the camera's photo album viewer - if(!options.saveToPhotoAlbum){ - FileConnection fconnIn = null; - FileConnection fconnOut = null; - InputStream in = null; - OutputStream out = null; - String newOutName = ""; - try - { - fconnIn = (FileConnection)Connector.open(filePath); - if (fconnIn.exists()) - { - newOutName = "file:///store/home/user/"+fconnIn.getName(); - fconnOut = (FileConnection)Connector.open(newOutName); - if (!fconnOut.exists()) - { - fconnOut.create(); - in = fconnIn.openInputStream(); - out = fconnOut.openOutputStream(); - out.write(IOUtilities.streamToBytes(in, 96*1024)); - fconnIn.delete(); - out.close(); - imageURIorData = newOutName; - filePath = newOutName; - waitForImageFile(newOutName); - } - } - } - finally - { - if (in != null) in.close(); - if (out != null) out.close(); - if (fconnIn != null) fconnIn.close(); - if (fconnOut != null) fconnOut.close(); - } - - } - - if (options.reformat) { - imageURIorData = reformatImage(filePath, options); - } else if (options.destinationType == CameraOptions.DESTINATION_DATA_URL) { - imageURIorData = encodeImage(filePath); - } - - // we have to check the size to avoid memory errors in the browser - if (imageURIorData.length() > MAX_ENCODING_SIZE) - { - // it's a big one. this is for your own good. - String msg = "Encoded image is too large. Try reducing camera image size."; - Logger.log(Camera.class.getName() + ": " + msg); - result = new PluginResult(PluginResult.Status.ERROR, msg); - } - else - { - result = new PluginResult(PluginResult.Status.OK, imageURIorData); - } - } - catch (Exception e) - { - result = new PluginResult(PluginResult.Status.IO_EXCEPTION, e.toString()); - } - - // send result back to JavaScript - sendResult(result, callbackId); - } - - /** - * Waits for the image file to be fully written to the file system. - * @param filePath Full path of the image file - * @throws IOException - */ - private static void waitForImageFile(String filePath) throws IOException - { - long start = (new Date()).getTime(); - FileConnection fconn = null; - try - { - fconn = (FileConnection)Connector.open(filePath, Connector.READ); - if (fconn.exists()) - { - long fileSize = fconn.fileSize(); - long size = 0; - while (true) - { - try { Thread.sleep(100); } catch (InterruptedException e) {} - size = fconn.fileSize(); - if (size == fileSize) { - break; - } - fileSize = size; - } - Logger.log(Camera.class.getName() + ": " + filePath + - " size=" + Long.toString(fileSize) + " bytes"); - } - } - finally - { - if (fconn != null) fconn.close(); - } - long end = (new Date()).getTime(); - Logger.log(Camera.class.getName() + ": wait time=" + Long.toString(end-start) + " ms"); - } - - /** - * Opens the specified image file and converts its contents to a Base64-encoded string. - * @param filePath Full path of the image file - * @return file contents as a Base64-encoded String - */ - private static String encodeImage(String filePath) throws IOException - { - String imageData = null; - - // open the image file - FileConnection fconn = null; - InputStream in = null; - ByteArrayOutputStream byteArrayOS = null; - try - { - fconn = (FileConnection)Connector.open(filePath); - if (fconn.exists()) - { - // encode file contents using BASE64 encoding - in = fconn.openInputStream(); - byteArrayOS = new ByteArrayOutputStream(); - Base64OutputStream base64OS = new Base64OutputStream(byteArrayOS); - base64OS.write(IOUtilities.streamToBytes(in, 96*1024)); - base64OS.flush(); - base64OS.close(); - imageData = byteArrayOS.toString(); - - Logger.log(Camera.class.getName() + ": Base64 encoding size=" + - Integer.toString(imageData.length())); - } - } - finally - { - if (in != null) in.close(); - if (fconn != null) fconn.close(); - if (byteArrayOS != null) byteArrayOS.close(); - } - - return imageData; - } - - /** - * Reformats the image taken with the camera based on the options specified. - * - * Unfortunately, reformatting the image will cause EXIF data in the photo - * to be lost. Most importantly the orientation data is lost so the - * picture is not auto rotated by software that recognizes EXIF data. - * - * @param filePath - * The full path of the image file - * @param options - * Specifies the format of the image and the result - * @return the reformatted image file URI or Base64-encoded image - * @throws IOException - */ - private static String reformatImage(String filePath, CameraOptions options) - throws IOException { - long start = (new Date()).getTime(); - - // Open the original image created by the camera application and read - // it into an EncodedImage object. - FileConnection fconn = null; - InputStream in = null; - Bitmap originalImage = null; - try { - fconn = (FileConnection) Connector.open(filePath); - in = fconn.openInputStream(); - originalImage = Bitmap.createBitmapFromBytes(IOUtilities.streamToBytes(in, 96*1024), 0, -1, 1); - } finally { - if (in != null) - in.close(); - if (fconn != null) - fconn.close(); - } - - int newWidth = options.targetWidth; - int newHeight = options.targetHeight; - int origWidth = originalImage.getWidth(); - int origHeight = originalImage.getHeight(); - - // If only width or only height was specified, the missing dimension is - // set based on the current aspect ratio of the image. - if (newWidth > 0 && newHeight <= 0) { - newHeight = (newWidth * origHeight) / origWidth; - } else if (newWidth <= 0 && newHeight > 0) { - newWidth = (newHeight * origWidth) / origHeight; - } else if (newWidth <= 0 && newHeight <= 0) { - newWidth = origWidth; - newHeight = origHeight; - } else { - // If the user specified both a positive width and height - // (potentially different aspect ratio) then the width or height is - // scaled so that the image fits while maintaining aspect ratio. - // Alternatively, the specified width and height could have been - // kept and Bitmap.SCALE_TO_FIT specified when scaling, but this - // would result in whitespace in the new image. - double newRatio = newWidth / (double)newHeight; - double origRatio = origWidth / (double)origHeight; - - if (origRatio > newRatio) { - newHeight = (newWidth * origHeight) / origWidth; - } else if (origRatio < newRatio) { - newWidth = (newHeight * origWidth) / origHeight; - } - } - - Bitmap newImage = new Bitmap(newWidth, newHeight); - originalImage.scaleInto(newImage, options.imageFilter, Bitmap.SCALE_TO_FILL); - - // Convert the image to the appropriate encoding. PNG does not allow - // quality to be specified so the only affect that the quality option - // has for a PNG is on the seelction of the image filter. - EncodedImage encodedImage; - if (options.encoding == CameraOptions.ENCODING_PNG) { - encodedImage = PNGEncodedImage.encode(newImage); - } else { - encodedImage = JPEGEncodedImage.encode(newImage, options.quality); - } - - // Rewrite the modified image back out to the same file. This is done - // to ensure that for every picture taken, only one shows up in the - // gallery. If the encoding changed the file extension will differ - // from the original. - OutputStream out = null; - int dirIndex = filePath.lastIndexOf('/'); - String filename = filePath.substring(dirIndex + 1, filePath.lastIndexOf('.')) - + options.fileExtension; - try { - fconn = (FileConnection) Connector.open(filePath); - fconn.truncate(0); - out = fconn.openOutputStream(); - out.write(encodedImage.getData()); - fconn.rename(filename); - } finally { - if (out != null) - out.close(); - if (fconn != null) - fconn.close(); - } - - // Return either the Base64-encoded string or the image URI for the - // new image. - String imageURIorData; - if (options.destinationType == CameraOptions.DESTINATION_DATA_URL) { - ByteArrayOutputStream byteArrayOS = null; - - try { - byteArrayOS = new ByteArrayOutputStream(); - Base64OutputStream base64OS = new Base64OutputStream( - byteArrayOS); - base64OS.write(encodedImage.getData()); - base64OS.flush(); - base64OS.close(); - imageURIorData = byteArrayOS.toString(); - Logger.log(Camera.class.getName() + ": Base64 encoding size=" - + Integer.toString(imageURIorData.length())); - } finally { - if (byteArrayOS != null) { - byteArrayOS.close(); - } - } - } else { - imageURIorData = filePath.substring(0, dirIndex + 1) + filename; - } - - long end = (new Date()).getTime(); - Logger.log(Camera.class.getName() + ": reformat time=" + Long.toString(end-start) + " ms"); - - return imageURIorData; - } - - /** - * Sends result back to JavaScript. - * @param result PluginResult - */ - private static void sendResult(PluginResult result, String callbackId) - { - // invoke the appropriate callback - if (result.getStatus() == PluginResult.Status.OK.ordinal()) - { - success(result, callbackId); - } - else - { - error(result, callbackId); - } - } -} http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/ac0c95be/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/camera/CameraOptions.java ---------------------------------------------------------------------- diff --git a/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/camera/CameraOptions.java b/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/camera/CameraOptions.java deleted file mode 100644 index 8bfa0df..0000000 --- a/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/camera/CameraOptions.java +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.cordova.camera; - -import org.apache.cordova.json4j.JSONArray; -import org.apache.cordova.json4j.JSONException; - -import net.rim.device.api.system.Bitmap; - -/** - * A helper class to hold all the options specified when using the camera api. - */ -public class CameraOptions { - - /** Return the result as a Base-64 encoded string. */ - public static final int DESTINATION_DATA_URL = 0; - - /** Return the result as a file URI. */ - public static final int DESTINATION_FILE_URI = 1; - - /** JPEG image encoding. */ - public static final int ENCODING_JPEG = 0; - - /** PNG image encoding. */ - public static final int ENCODING_PNG = 1; - - /** Select image from picture library. */ - public static final int SOURCE_PHOTOLIBRARY = 0; - - /** Take picture from camera. */ - public static final int SOURCE_CAMERA = 1; - - /** Select image from picture library. */ - public static final int SOURCE_SAVEDPHOTOALBUM = 2; - - // Class members with defaults set. - public int quality = 80; - public int destinationType = DESTINATION_DATA_URL; - public int sourceType = SOURCE_CAMERA; - public int targetWidth = -1; - public int targetHeight = -1; - public int encoding = ENCODING_JPEG; - public String fileExtension = ".jpg"; - public int imageFilter = Bitmap.FILTER_LANCZOS; - public boolean reformat = false; - public boolean saveToPhotoAlbum = true; - - /** - * Defines the order of args in the JSONArray - * - * [ 80, // quality - * Camera.DestinationType.DATA_URL, // destinationType - * Camera.PictureSourceType.PHOTOLIBRARY // sourceType (ignored) - * 400, // targetWidth - * 600, // targetHeight - * Camera.EncodingType.JPEG // encoding - * Camera.mediaType - * Camera.allowEdit - * Camera.correctOrientation - * Camera.saveToPhotoAlbum // save to photo album - * Camera.popoverOptions] - */ - private static final int ARG_QUALITY = 0; - private static final int ARG_DESTINATION_TYPE = 1; - private static final int ARG_SOURCE_TYPE = 2; - private static final int ARG_TARGET_WIDTH = 3; - private static final int ARG_TARGET_HEIGHT = 4; - private static final int ARG_ENCODING = 5; - private static final int ARG_SAVETOPHOTOALBUM = 9; - - /** - * Parse the JSONArray and populate the class members with the values. - * - * @param args - * a JSON Array of camera options. - * @return a new CameraOptions object with values set. - * @throws NumberFormatException - * @throws JSONException - */ - public static CameraOptions fromJSONArray(JSONArray args) - throws NumberFormatException, JSONException { - CameraOptions options = new CameraOptions(); - - if (args != null && args.length() > 0) { - // Use the quality value to determine what image filter to use - // if a reformat is necessary. The possible values in order from - // fastest (poorest quality) to slowest (best quality) are: - // - // FILTER_BOX -> FILTER_BILINEAR -> FILTER_LANCZOS - if (!args.isNull(ARG_QUALITY)) { - int quality = Integer.parseInt(args.getString(ARG_QUALITY)); - if (quality > 0) { - options.quality = quality > 100 ? 100 : quality; - if (options.quality < 30) { - options.imageFilter = Bitmap.FILTER_BOX; - } else if (options.quality < 60) { - options.imageFilter = Bitmap.FILTER_BILINEAR; - } - } - } - - if (!args.isNull(ARG_DESTINATION_TYPE)) { - int destType = Integer.parseInt(args - .getString(ARG_DESTINATION_TYPE)); - if (destType == DESTINATION_FILE_URI) { - options.destinationType = DESTINATION_FILE_URI; - } - } - - if (!args.isNull(ARG_SOURCE_TYPE)) { - options.sourceType = Integer.parseInt(args - .getString(ARG_SOURCE_TYPE)); - } - - if (!args.isNull(ARG_TARGET_WIDTH)) { - options.targetWidth = Integer.parseInt(args - .getString(ARG_TARGET_WIDTH)); - } - - if (!args.isNull(ARG_TARGET_HEIGHT)) { - options.targetHeight = Integer.parseInt(args - .getString(ARG_TARGET_HEIGHT)); - } - - if (!args.isNull(ARG_ENCODING)) { - int encoding = Integer.parseInt(args.getString(ARG_ENCODING)); - if (encoding == ENCODING_PNG) { - options.encoding = ENCODING_PNG; - options.fileExtension = ".png"; - } - } - - // A reformat of the picture taken from the camera is only performed - // if a custom width or height was specified or the user wants - // the output in an encoded form which is not JPEG. - if (options.targetWidth > 0 || options.targetHeight > 0 - || options.encoding != ENCODING_JPEG) { - options.reformat = true; - } - - if (!args.isNull(ARG_SAVETOPHOTOALBUM)) { - options.saveToPhotoAlbum = parseBoolean(args.getString(ARG_SAVETOPHOTOALBUM)); - } - - } - - return options; - } - - /** - * no parseBoolean in JDK 1.3 :( - */ - public static boolean parseBoolean(String s) { - if(s.equals("true")){ - return true; - }else{ - return false; - } - } - - /** - * @see java.lang.Object#toString() - */ - public String toString() { - StringBuffer str = new StringBuffer(); - str.append("Destination: " + destinationType + "\n"); - str.append("Source: " + sourceType + "\n"); - str.append("Quality: " + quality + "\n"); - str.append("Width: " + targetWidth + "\n"); - str.append("Height: " + targetHeight + "\n"); - str.append("Encoding: " + encoding + "\n"); - str.append("Filter: " + imageFilter + "\n"); - str.append("Reformat: " + reformat); - str.append("Save To Photo Album: " + saveToPhotoAlbum); - return str.toString(); - } -} http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/ac0c95be/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/camera/PhotoListener.java ---------------------------------------------------------------------- diff --git a/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/camera/PhotoListener.java b/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/camera/PhotoListener.java deleted file mode 100644 index 8571788..0000000 --- a/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/camera/PhotoListener.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.cordova.camera; - -import net.rim.device.api.io.file.FileSystemJournal; -import net.rim.device.api.io.file.FileSystemJournalEntry; -import net.rim.device.api.io.file.FileSystemJournalListener; -import net.rim.device.api.ui.UiApplication; - -/** - * Listens for photo added to file system and invokes the specified callback - * with the result formatted according the specified destination type. - */ -public class PhotoListener implements FileSystemJournalListener { - - /** - * Image format options specified by the caller. - */ - private CameraOptions options; - - /** - * Callback to be invoked with the result. - */ - private String callbackId; - - /** - * Used to track file system changes. - */ - private long lastUSN = 0; - - /** - * Constructor. - * @param options Specifies the format of the image and result - * @param callbackId The id of the callback to receive the result - */ - public PhotoListener(CameraOptions options, String callbackId) - { - this.options = options; - this.callbackId = callbackId; - } - - /** - * Listens for file system changes. When a JPEG file is added, we process - * it and send it back. - */ - public void fileJournalChanged() - { - // next sequence number file system will use - long USN = FileSystemJournal.getNextUSN(); - - for (long i = USN - 1; i >= lastUSN && i < USN; --i) - { - FileSystemJournalEntry entry = FileSystemJournal.getEntry(i); - if (entry == null) - { - break; - } - - if (entry.getEvent() == FileSystemJournalEntry.FILE_ADDED) - { - String path = entry.getPath(); - if (path != null && path.indexOf(".jpg") != -1) - { - // we found a new JPEG file - // first, stop listening to avoid processing the file more than once - synchronized(UiApplication.getEventLock()) { - UiApplication.getUiApplication().removeFileSystemJournalListener(this); - } - - // process the image on a background thread to avoid clogging the event queue - final String filePath = "file://" + path; - Thread thread = new Thread(new Runnable() { - public void run() { - Camera.processImage(filePath, options, callbackId); - } - }); - thread.start(); - - // clean up - Camera.closeCamera(); - - break; - } - } - } - - // remember the file journal change number, - // so we don't search the same events again and again - lastUSN = USN; - } -} http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/ac0c95be/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/capture/AudioCaptureListener.java ---------------------------------------------------------------------- diff --git a/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/capture/AudioCaptureListener.java b/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/capture/AudioCaptureListener.java deleted file mode 100644 index 9267e9b..0000000 --- a/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/capture/AudioCaptureListener.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.cordova.capture; - -import net.rim.device.api.io.file.FileSystemJournal; -import net.rim.device.api.io.file.FileSystemJournalEntry; -import net.rim.device.api.io.file.FileSystemJournalListener; - -/** - * Listens for audio recording files that are added to file system. - *

- * Audio recordings are added to the file system when the user stops the - * recording. The audio recording file extension is '.amr'. Therefore, we listen - * for the FileSystemJournalEntry.FILE_ADDED event, capturing when - * the new file is written. - *

- * The file system notifications will arrive on the application event thread. - * When it receives a notification, it adds the image file path to a MediaQueue - * so that the capture thread can process the file. - */ -public class AudioCaptureListener implements FileSystemJournalListener { - /** - * Used to track file system changes. - */ - private long lastUSN = 0; - - /** - * Queue to send media files to for processing. - */ - private MediaQueue queue = null; - - /** - * Constructor. - */ - AudioCaptureListener(MediaQueue queue) { - this.queue = queue; - } - - public void fileJournalChanged() { - // next sequence number file system will use - long USN = FileSystemJournal.getNextUSN(); - - for (long i = USN - 1; i >= lastUSN && i < USN; --i) { - FileSystemJournalEntry entry = FileSystemJournal.getEntry(i); - if (entry == null) { - break; - } - - // has audio recording file has been added to the file system? - String path = entry.getPath(); - if (entry.getEvent() == FileSystemJournalEntry.FILE_ADDED - && path.endsWith(".amr")) { - // add file path to the capture queue - queue.add("file://" + path); - - break; - } - } - - // remember the file journal change number, - // so we don't search the same events again and again - lastUSN = USN; - } -} http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/ac0c95be/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/capture/AudioCaptureOperation.java ---------------------------------------------------------------------- diff --git a/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/capture/AudioCaptureOperation.java b/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/capture/AudioCaptureOperation.java deleted file mode 100644 index f4fd9b4..0000000 --- a/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/capture/AudioCaptureOperation.java +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.cordova.capture; - -import java.io.IOException; -import java.util.Date; - -import javax.microedition.io.Connector; -import javax.microedition.io.file.FileConnection; - -import org.apache.cordova.file.File; -import org.apache.cordova.util.FileUtils; -import org.apache.cordova.util.Logger; - -import net.rim.device.api.io.MIMETypeAssociations; -import net.rim.device.api.ui.UiApplication; - -public class AudioCaptureOperation extends CaptureOperation { - - // content type - public static final String CONTENT_TYPE = "audio/"; - - // maximum duration to capture media (milliseconds) - private double duration = 0; - - // file system listener - private AudioCaptureListener listener = null; - - /** - * Creates and starts an audio capture operation. - * - * @param limit - * maximum number of media files to capture - * @param duration - * maximum duration to capture media (milliseconds) - * @param callbackId - * the callback to receive the files - * @param queue - * the queue from which to retrieve captured media files - */ - public AudioCaptureOperation(long limit, double duration, String callbackId, MediaQueue queue) { - super(limit, callbackId, queue); - - if (duration > 0) { - this.duration = duration; - } - - // listener to capture image files added to file system - this.listener = new AudioCaptureListener(queue); - - start(); - } - - /** - * Registers file system listener and launches native voice notes recorder - * application. - */ - protected void setup() { - // register listener for files being written - synchronized(UiApplication.getEventLock()) { - UiApplication.getUiApplication().addFileSystemJournalListener(listener); - } - - // launch the native voice notes recorder application - AudioControl.launchAudioRecorder(); - } - - /** - * Unregisters file system listener and closes native voice notes recorder - * application. - */ - protected void teardown() { - // remove file system listener - synchronized(UiApplication.getEventLock()) { - UiApplication.getUiApplication().removeFileSystemJournalListener(listener); - } - - // close the native voice notes recorder application - AudioControl.closeAudioRecorder(); - } - - /** - * Retrieves the file properties for the captured audio recording. - * - * @param filePath - * full path of the audio recording file - */ - protected void processFile(String filePath) { - Logger.log(this.getClass().getName() + ": processing file: " + filePath); - - // wait for file to finish writing and add it to captured files - addCaptureFile(getMediaFile(filePath)); - } - - /** - * Waits for file to be fully written to the file system before retrieving - * its file properties. - * - * @param filePath - * Full path of the image file - * @throws IOException - */ - private File getMediaFile(String filePath) { - File file = new File(FileUtils.stripSeparator(filePath)); - - // time begin waiting for file write - long start = (new Date()).getTime(); - - // wait for the file to be fully written, then grab its properties - FileConnection fconn = null; - try { - fconn = (FileConnection) Connector.open(filePath, Connector.READ); - if (fconn.exists()) { - // wait for file to be fully written - long fileSize = fconn.fileSize(); - long size = 0; - Thread thisThread = Thread.currentThread(); - while (myThread == thisThread) { - try { - Thread.sleep(100); - } - catch (InterruptedException e) { - break; - } - size = fconn.fileSize(); - if (fileSize != 0 && size == fileSize) { - break; - } - fileSize = size; - } - Logger.log(this.getClass().getName() + ": " + filePath + " size=" - + Long.toString(fileSize) + " bytes"); - - // retrieve file properties - file.setLastModifiedDate(fconn.lastModified()); - file.setName(FileUtils.stripSeparator(fconn.getName())); - file.setSize(fileSize); - file.setType(MIMETypeAssociations.getMIMEType(filePath)); - } - } - catch (IOException e) { - Logger.log(this.getClass().getName() + ": " + e); - } - finally { - try { - if (fconn != null) fconn.close(); - } catch (IOException ignored) {} - } - - // log time it took to write the file - long end = (new Date()).getTime(); - Logger.log(this.getClass().getName() + ": wait time=" - + Long.toString(end - start) + " ms"); - - return file; - } -} http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/ac0c95be/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/capture/AudioControl.java ---------------------------------------------------------------------- diff --git a/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/capture/AudioControl.java b/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/capture/AudioControl.java deleted file mode 100644 index 45e9f9c..0000000 --- a/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/capture/AudioControl.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.cordova.capture; - -import org.apache.cordova.util.ApplicationUtils; -import org.apache.cordova.util.Logger; - -import net.rim.device.api.system.ApplicationDescriptor; -import net.rim.device.api.system.ApplicationManager; -import net.rim.device.api.system.ApplicationManagerException; -import net.rim.device.api.system.CodeModuleManager; - -public class AudioControl { - /** - * Determines if the native voice notes recorder application is installed - * on the device. - * - * @return true if native voice notes recorder application is installed - */ - public static boolean hasAudioRecorderApplication() { - return ApplicationUtils.isModuleInstalled("net_rim_bb_voicenotesrecorder"); - } - - /** - * Determines if the native voice notes recorder application is running in - * the foreground. - * - * @return true if native voice notes recorder application is running in - * foreground - */ - public static boolean isAudioRecorderActive() { - return ApplicationUtils.isApplicationInForeground("net_rim_bb_voicenotesrecorder"); - } - - /** - * Launches the native audio recorder application. - */ - public static void launchAudioRecorder() { - int handle = CodeModuleManager.getModuleHandle("net_rim_bb_voicenotesrecorder"); - ApplicationDescriptor ad = CodeModuleManager.getApplicationDescriptors(handle)[0]; - ApplicationDescriptor ad2 = new ApplicationDescriptor(ad, null); - try { - ApplicationManager.getApplicationManager().runApplication(ad2, true); - } - catch (ApplicationManagerException e) { - Logger.log(AudioControl.class.getName() + ": unable to launch net_rim_bb_voicenotesrecorder"); - } - } - - /** - * Closes the native audio recorder application. - */ - public static void closeAudioRecorder() { - if (!isAudioRecorderActive()) { - return; - } - ApplicationUtils.injectEscKeyPress(1); - } -} http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/ac0c95be/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/capture/CameraControl.java ---------------------------------------------------------------------- diff --git a/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/capture/CameraControl.java b/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/capture/CameraControl.java deleted file mode 100644 index 2ed9206..0000000 --- a/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/capture/CameraControl.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.cordova.capture; - -import org.apache.cordova.util.ApplicationUtils; - -import net.rim.blackberry.api.invoke.CameraArguments; -import net.rim.blackberry.api.invoke.Invoke; -import net.rim.device.api.ui.UiApplication; - -public class CameraControl { - /** - * Determines if the native camera application is running in the foreground. - * - * @return true if native camera application is running in foreground - */ - public static boolean isCameraActive() { - return ApplicationUtils.isApplicationInForeground("net_rim_bb_camera"); - } - - /** - * Determines if the native video recorder application is running in the - * foreground. - * - * @return true if native video recorder application is running in - * foreground - */ - public static boolean isVideoRecorderActive() { - return ApplicationUtils.isApplicationInForeground("net_rim_bb_videorecorder"); - } - - /** - * Launches the native camera application. - */ - public static void launchCamera() { - synchronized(UiApplication.getEventLock()) { - Invoke.invokeApplication(Invoke.APP_TYPE_CAMERA, - new CameraArguments()); - } - } - - /** - * Launches the native video recorder application. - */ - public static void launchVideoRecorder() { - synchronized(UiApplication.getEventLock()) { - Invoke.invokeApplication(Invoke.APP_TYPE_CAMERA, - new CameraArguments(CameraArguments.ARG_VIDEO_RECORDER)); - } - } - - /** - * Closes the native camera application. - */ - public static void closeCamera() { - if (!isCameraActive()) { - return; - } - ApplicationUtils.injectEscKeyPress(2); - } - - /** - * Closes the native video recorder application. - */ - public static void closeVideoRecorder() { - if (!isVideoRecorderActive()) { - return; - } - ApplicationUtils.injectEscKeyPress(2); - } -} http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/ac0c95be/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/capture/CaptureControl.java ---------------------------------------------------------------------- diff --git a/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/capture/CaptureControl.java b/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/capture/CaptureControl.java deleted file mode 100644 index e37dd56..0000000 --- a/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/capture/CaptureControl.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.cordova.capture; - -import java.util.Enumeration; -import java.util.Vector; - -public class CaptureControl { - - /** - * Pending capture operations. - */ - private Vector pendingOperations = new Vector(); - - /** - * Singleton. - */ - private CaptureControl() {} - - /** - * Holds the singleton for lazy instantiation. - */ - private static class CaptureControlHolder { - static final CaptureControl INSTANCE = new CaptureControl(); - } - - /** - * Retrieves a CaptureControl instance. - * @return CaptureControl instance. - */ - public static final CaptureControl getCaptureControl() { - return CaptureControlHolder.INSTANCE; - } - - /** - * Add capture operation so we can stop it manually. - */ - public void addCaptureOperation(CaptureOperation operation) { - if (operation == null) { - return; - } - - synchronized (pendingOperations) { - pendingOperations.addElement(operation); - } - } - - /** - * Remove capture operation. - */ - public void removeCaptureOperation(CaptureOperation operation) { - if (operation == null) { - return; - } - - synchronized (pendingOperations) { - pendingOperations.removeElement(operation); - } - } - - /** - * Starts an image capture operation, during which a user can take multiple - * photos. The capture operation runs in the background. - * - * @param limit - * the maximum number of images to capture during the operation - * @param callbackId - * the callback to be invoked with capture file properties - */ - public void startImageCaptureOperation(long limit, String callbackId) { - // setup a queue to receive image file paths - MediaQueue queue = new MediaQueue(); - - // start a capture operation on a background thread - CaptureOperation operation = new ImageCaptureOperation(limit, - callbackId, queue); - - // track the operation so we can stop or cancel it later - addCaptureOperation(operation); - } - - /** - * Starts a video capture operation, during which a user can record multiple - * recordings. The capture operation runs in the background. - * - * @param limit - * the maximum number of images to capture during the operation - * @param callbackId - * the callback to be invoked with capture file properties - */ - public void startVideoCaptureOperation(long limit, String callbackId) { - // setup a queue to receive video recording file paths - MediaQueue queue = new MediaQueue(); - - // start a capture operation on a background thread - CaptureOperation operation = new VideoCaptureOperation(limit, - callbackId, queue); - - // track the operation so we can stop or cancel it later - addCaptureOperation(operation); - } - - /** - * Starts an audio capture operation using the native voice notes recorder - * application. - * - * @param limit - * the maximum number of audio clips to capture during the - * operation - * @param duration - * the maximum duration of each captured clip - * @param callbackId - * the callback to be invoked with the capture results - */ - public void startAudioCaptureOperation(long limit, double duration, String callbackId) { - // setup a queue to receive recording file paths - MediaQueue queue = new MediaQueue(); - - // start a capture operation on a background thread - CaptureOperation operation = new AudioCaptureOperation(limit, duration, - callbackId, queue); - - // track the operation so we can stop or cancel it later - addCaptureOperation(operation); - } - - /** - * Stops all pending capture operations. If the cancel - * parameter is true, no results will be sent via the callback - * mechanism and any captured files will be removed from the file system. - * - * @param cancel - * true if operations should be canceled - */ - public void stopPendingOperations(boolean cancel) { - // There are two scenarios where the capture operation would be stopped - // manually: - // 1- The user stops the capture application, and this application - // returns to the foreground. - // 2- It is canceled programmatically. No results should be sent. - synchronized (pendingOperations) { - for (Enumeration e = pendingOperations.elements(); e.hasMoreElements(); ) { - CaptureOperation operation = (CaptureOperation) e.nextElement(); - if (cancel) { - operation.cancel(); - } - else { - operation.stop(); - } - } - } - } -} http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/ac0c95be/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/capture/CaptureMode.java ---------------------------------------------------------------------- diff --git a/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/capture/CaptureMode.java b/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/capture/CaptureMode.java deleted file mode 100644 index 7c71f96..0000000 --- a/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/capture/CaptureMode.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.cordova.capture; - -import org.apache.cordova.json4j.JSONException; -import org.apache.cordova.json4j.JSONObject; - -public class CaptureMode { - - private String mimeType = null; - private long height = 0; - private long width = 0; - - public CaptureMode() { - } - - public CaptureMode(String type) { - this.mimeType = type; - } - - public CaptureMode(String type, long width, long height) { - this.mimeType = type; - this.height = height; - this.width = width; - } - - public String getMimeType() { - return mimeType; - } - - public long getHeight() { - return height; - } - - public long getWidth() { - return width; - } - - public JSONObject toJSONObject() { - JSONObject o = new JSONObject(); - try { - o.put("type", getMimeType()); - o.put("height", getHeight()); - o.put("width", getWidth()); - } - catch (JSONException ignored) { - } - return o; - } - - public boolean equals(Object o) { - if (o == this) { - return true; - } - if (!(o instanceof CaptureMode)) { - return false; - } - CaptureMode cm = (CaptureMode)o; - return ((mimeType == null ? cm.mimeType == null : - mimeType.equals(cm.mimeType)) - && (width == cm.width) - && (height == cm.height)); - } - - public int hashCode() { - int hash = (mimeType != null ? mimeType.hashCode() : 19); - hash = 37*hash + (int)width; - hash = 37*hash + (int)height; - return hash; - } -} http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/ac0c95be/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/capture/CaptureOperation.java ---------------------------------------------------------------------- diff --git a/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/capture/CaptureOperation.java b/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/capture/CaptureOperation.java deleted file mode 100644 index dc85bd8..0000000 --- a/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/capture/CaptureOperation.java +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.cordova.capture; - -import java.io.IOException; -import java.util.Enumeration; -import java.util.Vector; - -import org.apache.cordova.file.File; -import org.apache.cordova.util.FileUtils; -import org.apache.cordova.util.Logger; - -public abstract class CaptureOperation implements Runnable { - // max number of media files to capture - protected long limit = 1; - - // for sending results - protected String callbackId = null; - - // list of captured media files - protected final Vector captureFiles = new Vector(); - - // media file queue - protected MediaQueue mediaQueue = null; - - // used to interrupt thread - protected volatile Thread myThread; - - // to determine if operation has been canceled - protected boolean canceled = false; - - /** - * Creates and starts a capture operation on a new thread. - * - * @param limit - * maximum number of media files to capture - * @param callbackId - * the callback to receive the files - * @param queue - * the queue from which to retrieve captured media files - */ - public CaptureOperation(long limit, String callbackId, MediaQueue queue) { - if (limit > 1) { - this.limit = limit; - } - - this.callbackId = callbackId; - this.mediaQueue = queue; - this.myThread = new Thread(this); - } - - /** - * Waits for media file to be captured. - */ - public void run() { - if (myThread == null) { - return; // stopped before started - } - - Logger.log(this.getClass().getName() + ": " + callbackId + " started"); - - // tasks to be run before entering main loop - setup(); - - // capture until interrupted or we've reached capture limit - Thread thisThread = Thread.currentThread(); - String filePath = null; - while (myThread == thisThread && captureFiles.size() < limit) { - try { - // consume file added to media capture queue - filePath = mediaQueue.remove(); - } - catch (InterruptedException e) { - Logger.log(this.getClass().getName() + ": " + callbackId + " interrupted"); - // and we're done - break; - } - processFile(filePath); - } - - // perform cleanup tasks - teardown(); - - // process captured results - processResults(); - - // unregister the operation from the controller - CaptureControl.getCaptureControl().removeCaptureOperation(this); - - Logger.log(this.getClass().getName() + ": " + callbackId + " finished"); - } - - /** - * Starts this capture operation on a new thread. - */ - protected void start() { - if (myThread == null) { - return; // stopped before started - } - myThread.start(); - } - - /** - * Stops the operation. - */ - public void stop() { - // interrupt capture thread - Thread tmpThread = myThread; - myThread = null; - if (tmpThread != null && tmpThread.isAlive()) { - tmpThread.interrupt(); - } - } - - /** - * Cancels the operation. - */ - public void cancel() { - canceled = true; - stop(); - } - - /** - * Processes the results of the capture operation. - */ - protected void processResults() { - // process results - if (!canceled) { - // invoke appropriate callback - if (captureFiles.size() > 0) { - // send capture files - MediaCapture.captureSuccess(captureFiles, callbackId); - } - else { - // error - MediaCapture.captureError(callbackId); - } - } - else { - removeCaptureFiles(); - } - } - - /** - * Adds a media file to list of collected media files for this operation. - * - * @param file - * object containing media file properties - */ - protected void addCaptureFile(File file) { - captureFiles.addElement(file); - } - - /** - * Removes captured files from the file system. - */ - protected void removeCaptureFiles() { - for (Enumeration e = captureFiles.elements(); e.hasMoreElements();) { - File file = (File) e.nextElement(); - try { - FileUtils.delete(file.getFullPath()); - } - catch (IOException ignored) { - } - } - } - - /** - * Override this method to perform tasks before the operation starts. - */ - protected void setup() { - } - - /** - * Override this method to perform tasks after the operation has - * stopped. - */ - protected void teardown() { - } - - /** - * Subclasses must implement this method to process a captured media file. - * @param filePath the full path of the media file - */ - protected abstract void processFile(final String filePath); -} http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/ac0c95be/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/capture/ImageCaptureListener.java ---------------------------------------------------------------------- diff --git a/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/capture/ImageCaptureListener.java b/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/capture/ImageCaptureListener.java deleted file mode 100644 index 4906ee8..0000000 --- a/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/capture/ImageCaptureListener.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.cordova.capture; - -import net.rim.device.api.io.file.FileSystemJournal; -import net.rim.device.api.io.file.FileSystemJournalEntry; -import net.rim.device.api.io.file.FileSystemJournalListener; - -/** - * Listens for image files that are added to file system. - *

- * The file system notifications will arrive on the application event thread. - * When it receives a notification, it adds the image file path to a MediaQueue - * so that the capture thread can process the file. - */ -class ImageCaptureListener implements FileSystemJournalListener { - - /** - * Used to track file system changes. - */ - private long lastUSN = 0; - - /** - * Collection of media files. - */ - private MediaQueue queue = null; - - /** - * Constructor. - */ - ImageCaptureListener(MediaQueue queue) { - this.queue = queue; - } - - /** - * Listens for file system changes. When a JPEG file is added, we process - * it and send it back. - */ - public void fileJournalChanged() - { - // next sequence number file system will use - long USN = FileSystemJournal.getNextUSN(); - - for (long i = USN - 1; i >= lastUSN && i < USN; --i) - { - FileSystemJournalEntry entry = FileSystemJournal.getEntry(i); - if (entry == null) - { - break; - } - - if (entry.getEvent() == FileSystemJournalEntry.FILE_ADDED) - { - String path = entry.getPath(); - if (path != null && path.indexOf(".jpg") != -1) - { - // add file path to the capture queue - queue.add("file://" + path); - break; - } - } - } - - // remember the file journal change number, - // so we don't search the same events again and again - lastUSN = USN; - } -} http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/ac0c95be/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/capture/ImageCaptureOperation.java ---------------------------------------------------------------------- diff --git a/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/capture/ImageCaptureOperation.java b/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/capture/ImageCaptureOperation.java deleted file mode 100644 index a831dc2..0000000 --- a/lib/cordova-blackberry/framework/ext/src/org/apache/cordova/capture/ImageCaptureOperation.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.cordova.capture; - -import java.io.IOException; -import java.util.Date; -import javax.microedition.io.Connector; -import javax.microedition.io.file.FileConnection; - -import org.apache.cordova.file.File; -import org.apache.cordova.util.FileUtils; -import org.apache.cordova.util.Logger; - -import net.rim.device.api.io.MIMETypeAssociations; -import net.rim.device.api.ui.UiApplication; - -public class ImageCaptureOperation extends CaptureOperation { - // content type - public static String CONTENT_TYPE = "image/"; - - // file system listener - private ImageCaptureListener listener = null; - - /** - * Creates and starts an image capture operation. - * - * @param limit - * maximum number of media files to capture - * @param callbackId - * the callback to receive the files - * @param queue - * the queue from which to retrieve captured media files - */ - public ImageCaptureOperation(long limit, String callbackId, MediaQueue queue) { - super(limit, callbackId, queue); - - // listener to capture image files added to file system - this.listener = new ImageCaptureListener(queue); - - start(); - } - - /** - * Registers file system listener and launches native camera application. - */ - protected void setup() { - // register listener for files being written - synchronized(UiApplication.getEventLock()) { - UiApplication.getUiApplication().addFileSystemJournalListener(listener); - } - - // launch the native camera application - CameraControl.launchCamera(); - } - - /** - * Unregisters file system listener and closes native camera application. - */ - protected void teardown() { - // remove file system listener - synchronized(UiApplication.getEventLock()) { - UiApplication.getUiApplication().removeFileSystemJournalListener(listener); - } - - // close the native camera application - CameraControl.closeCamera(); - } - - /** - * Waits for image file to be written to file system and retrieves its file - * properties. - * - * @param filePath - * the full path of the media file - */ - protected void processFile(final String filePath) { - Logger.log(this.getClass().getName() + ": processing file: " + filePath); - - // wait for file to finish writing and add it to captured files - addCaptureFile(getMediaFile(filePath)); - } - - /** - * Waits for file to be fully written to the file system before retrieving - * its file properties. - * - * @param filePath - * Full path of the image file - * @throws IOException - */ - private File getMediaFile(String filePath) { - File file = new File(FileUtils.stripSeparator(filePath)); - - // time begin waiting for file write - long start = (new Date()).getTime(); - - // wait for the file to be fully written, then grab its properties - FileConnection fconn = null; - try { - fconn = (FileConnection) Connector.open(filePath, Connector.READ); - if (fconn.exists()) { - // wait for file to be fully written - long fileSize = fconn.fileSize(); - long size = 0; - Thread thisThread = Thread.currentThread(); - while (myThread == thisThread) { - try { - Thread.sleep(100); - } - catch (InterruptedException e) { - break; - } - size = fconn.fileSize(); - if (size == fileSize) { - break; - } - fileSize = size; - } - Logger.log(this.getClass().getName() + ": " + filePath + " size=" - + Long.toString(fileSize) + " bytes"); - - // retrieve file properties - file.setLastModifiedDate(fconn.lastModified()); - file.setName(FileUtils.stripSeparator(fconn.getName())); - file.setSize(fileSize); - file.setType(MIMETypeAssociations.getMIMEType(filePath)); - } - } - catch (IOException e) { - Logger.log(this.getClass().getName() + ": " + e); - } - finally { - try { - if (fconn != null) fconn.close(); - } catch (IOException ignored) {} - } - - // log time it took to write the file - long end = (new Date()).getTime(); - Logger.log(this.getClass().getName() + ": wait time=" - + Long.toString(end - start) + " ms"); - - return file; - } -}