content: /*
   * Copyright (C) 2008 ZXing authors
   *
   * 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 com.handsome.didi.zxing.camera;
  
  import android.content.Context;
  import android.graphics.Point;
  import android.hardware.Camera;
  import android.hardware.Camera.Size;
  import android.os.Handler;
  import android.util.Log;
  import android.view.SurfaceHolder;
  
  import com.handsome.didi.zxing.camera.open.OpenCameraInterface;
  
  import java.io.IOException;
  import java.util.List;
  
  
  /**
   * This object wraps the Camera service object and expects to be the only one
   * talking to it. The implementation encapsulates the steps needed to take
   * preview-sized images, which are used for both preview and decoding.
   * 
   * @author dswitkin@google.com (Daniel Switkin)
   */
  public class CameraManager {
  
  	private static final String TAG = CameraManager.class.getSimpleName();
  
  	private final Context context;
  	private final CameraConfigurationManager configManager;
  	private Camera camera;
  	private AutoFocusManager autoFocusManager;
  
  	private boolean initialized;
  	private boolean previewing;
  	private int requestedCameraId = -1;
  	/**
  	 * Preview frames are delivered here, which we pass on to the registered
  	 * handler. Make sure to clear the handler so it will only receive one
  	 * message.
  	 */
  	private final PreviewCallback previewCallback;
  
  	public CameraManager(Context context) {
  		this.context = context;
  		this.configManager = new CameraConfigurationManager(context);
  		previewCallback = new PreviewCallback(configManager);
  	}
  
  	/**
  	 * Opens the camera driver and initializes the hardware parameters.
  	 * 
  	 * @param holder
  	 *            The surface object which the camera will draw preview frames
  	 *            into.
  	 * @throws IOException
  	 *             Indicates the camera driver failed to open.
  	 */
  	public synchronized void openDriver(SurfaceHolder holder) throws IOException {
  		Camera theCamera = camera;
  		if (theCamera == null) {
  
  			if (requestedCameraId >= 0) {
  				theCamera = OpenCameraInterface.open(requestedCameraId);
  			} else {
  				theCamera = OpenCameraInterface.open();
  			}
  
  			if (theCamera == null) {
  				throw new IOException();
  			}
  			camera = theCamera;
  		}
  		theCamera.setPreviewDisplay(holder);
  
  		if (!initialized) {
  			initialized = true;
  			configManager.initFromCameraParameters(theCamera);
  		}
  
  		Camera.Parameters parameters = theCamera.getParameters();
  		String parametersFlattened = parameters == null ? null : parameters.flatten(); // Save
  																						// these,
  																						// temporarily
  		try {
  			configManager.setDesiredCameraParameters(theCamera, false);
  		} catch (RuntimeException re) {
  			// Driver failed
  			Log.w(TAG, "Camera rejected parameters. Setting only minimal safe-mode parameters");
  			Log.i(TAG, "Resetting to saved camera params: " + parametersFlattened);
  			// Reset:
  			if (parametersFlattened != null) {
  				parameters = theCamera.getParameters();
  				parameters.unflatten(parametersFlattened);
  				try {
  					theCamera.setParameters(parameters);
  					configManager.setDesiredCameraParameters(theCamera, true);
  				} catch (RuntimeException re2) {
  					// Well, darn. Give up
  					Log.w(TAG, "Camera rejected even safe-mode parameters! No configuration");
  				}
  			}
  		}
  
  	}
  
  	public synchronized boolean isOpen() {
  		return camera != null;
  	}
  
  	/**
  	 * Closes the camera driver if still in use.
  	 */
  	public synchronized void closeDriver() {
  		if (camera != null) {
  			camera.release();
  			camera = null;
  			// Make sure to clear these each time we close the camera, so that
  			// any scanning rect
  			// requested by intent is forgotten.
  		}
  	}
  
  	/**
  	 * Asks the camera hardware to begin drawing preview frames to the screen.
  	 */
  	public synchronized void startPreview() {
  		Camera theCamera = camera;
  		if (theCamera != null && !previewing) {
  			theCamera.startPreview();
  			previewing = true;
  			autoFocusManager = new AutoFocusManager(context, camera);
  		}
  	}
  
  	/**
  	 * Tells the camera to stop drawing preview frames.
  	 */
  	public synchronized void stopPreview() {
  		if (autoFocusManager != null) {
  			autoFocusManager.stop();
  			autoFocusManager = null;
  		}
  		if (camera != null && previewing) {
  			camera.stopPreview();
  			previewCallback.setHandler(null, 0);
  			previewing = false;
  		}
  	}
  
  	/**
  	 * A single preview frame will be returned to the handler supplied. The data
  	 * will arrive as byte[] in the message.obj field, with width and height
  	 * encoded as message.arg1 and message.arg2, respectively.
  	 * 
  	 * @param handler
  	 *            The handler to send the message to.
  	 * @param message
  	 *            The what field of the message to be sent.
  	 */
  	public synchronized void requestPreviewFrame(Handler handler, int message) {
  		Camera theCamera = camera;
  		if (theCamera != null && previewing) {
  			previewCallback.setHandler(handler, message);
  			theCamera.setOneShotPreviewCallback(previewCallback);
  		}
  	}
  
  	/**
  	 * Allows third party apps to specify the camera ID, rather than determine
  	 * it automatically based on available cameras and their orientation.
  	 * 
  	 * @param cameraId
  	 *            camera ID of the camera to use. A negative value means
  	 *            "no preference".
  	 */
  	public synchronized void setManualCameraId(int cameraId) {
  		requestedCameraId = cameraId;
  	}
  
  	/**
  	 * 获取相机分辨率
  	 * 
  	 * @return
  	 */
  	public Point getCameraResolution() {
  		return configManager.getCameraResolution();
  	}
  
  	public Size getPreviewSize() {
  		if (null != camera) {
  			return camera.getParameters().getPreviewSize();
  		}
  		return null;
  	}
  
  	/**
  	 * 通过设置Camera打开闪光灯
  	 */
  	public void turnLightOn() {
  		if (camera == null) {
  			return;
  		}
  		Camera.Parameters parameters = camera.getParameters();
  		if (parameters == null) {
  			return;
  		}
  
  		List<String> flashModes = parameters.getSupportedFlashModes();
  		if (flashModes == null) {
  			return;
  		}
  		String flashMode = parameters.getFlashMode();
  		Log.i(TAG, "Flash mode: " + flashMode);
  		Log.i(TAG, "Flash modes: " + flashModes);
  		// 闪光灯关闭状态
  		if (!Camera.Parameters.FLASH_MODE_TORCH.equals(flashMode)) {
  			// Turn on the flash
  			if (flashModes.contains(Camera.Parameters.FLASH_MODE_TORCH)) {
  				parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
  				camera.setParameters(parameters);
  				camera.startPreview();
  			} else {
  			}
  		}
  	}
  
  	/**
  	 * 通过设置Camera关闭闪光灯
  	 */
  	public void turnLightOff() {
  		if (camera == null) {
  			return;
  		}
  		Camera.Parameters parameters = camera.getParameters();
  		if (parameters == null) {
  			return;
  		}
  		List<String> flashModes = parameters.getSupportedFlashModes();
  		String flashMode = parameters.getFlashMode();
  		// Check if camera flash exists
  		if (flashModes == null) {
  			return;
  		}
  		// 闪光灯打开状态
  		if (!Camera.Parameters.FLASH_MODE_OFF.equals(flashMode)) {
  			// Turn off the flash
  			if (flashModes.contains(Camera.Parameters.FLASH_MODE_OFF)) {
  				parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
  				camera.setParameters(parameters);
  			} else {
  				Log.e(TAG, "FLASH_MODE_OFF not supported");
  			}
  		}
  	}
  }
  