/* * PhoneGap is available under *either* the terms of the modified BSD license *or* the * MIT License (2008). See http://opensource.org/licenses/alphabetical for full text. * * Copyright (c) 2011, IBM Corporation */ package com.phonegap.media; import java.io.IOException; import java.util.Enumeration; import java.util.Vector; import com.phonegap.file.File; import com.phonegap.file.FileUtils; import com.phonegap.util.Logger; public abstract class CaptureOperation implements Runnable { // max number of media files to capture protected int 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(int 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); }