/*
The contents of this file are subject to the Mozilla Public License
Version 1.1 (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.mozilla.org/MPL/
Software distributed under the License is distributed on an "AS IS"
basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
License for the specific language governing rights and limitations
under the License.
The Original Code is collection of files collectively known as Open Camera.
The Initial Developer of the Original Code is Almalence Inc.
Portions created by Initial Developer are Copyright (C) 2013
by Almalence Inc. All Rights Reserved.
*/
package com.almalence.plugins.vf.focus;
import java.util.ArrayList;
import java.util.List;
import android.content.SharedPreferences;
import android.content.res.AssetFileDescriptor;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.RectF;
import android.hardware.Camera.Area;
import android.os.Build;
import android.os.CountDownTimer;
import android.os.Handler;
import android.os.Message;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.Toast;
//<!-- -+-
import com.almalence.opencam.ApplicationInterface;
import com.almalence.opencam.ApplicationScreen;
import com.almalence.opencam.CameraParameters;
import com.almalence.opencam.PluginManager;
import com.almalence.opencam.PluginViewfinder;
import com.almalence.opencam.R;
import com.almalence.opencam.SoundPlayer;
import com.almalence.opencam.cameracontroller.CameraController;
//-+- -->
/* <!-- +++
import com.almalence.opencam_plus.ApplicationInterface;
import com.almalence.opencam_plus.ApplicationScreen;
import com.almalence.opencam_plus.cameracontroller.CameraController;
import com.almalence.opencam_plus.CameraParameters;
import com.almalence.opencam_plus.PluginManager;
import com.almalence.opencam_plus.PluginViewfinder;
import com.almalence.opencam_plus.R;
import com.almalence.opencam_plus.SoundPlayer;
+++ --> */
import com.almalence.util.Util;
/***
* Implements touch to focus functionality
***/
public class FocusVFPlugin extends PluginViewfinder
{
private static final String TAG = "AlmalenceFocusPlugin";
private static final int RESET_TOUCH_FOCUS = 0;
private static final int START_TOUCH_FOCUS = 1;
private static final int RESET_TOUCH_FOCUS_DELAY = 5000;
private static final int START_TOUCH_FOCUS_DELAY = 1500;
private int mState = STATE_INACTIVE;
private static final int STATE_INACTIVE = -1;
private static final int STATE_IDLE = 0; // Focus
// is
// not
// active.
private static final int STATE_FOCUSING = 1; // Focus
// is
// in
// progress.
// Focus is in progress and the camera should take a picture after focus
// finishes.
private static final int STATE_FOCUSING_SNAP_ON_FINISH = 2;
private static final int STATE_SUCCESS = 3; // Focus
// finishes
// and
// succeeds.
private static final int STATE_FAIL = 4; // Focus
// finishes
// and
// fails.
private long lastTouchTime1 = 0;
private long lastTouchTime2 = 0;
private boolean mFocusSupported = true;
private boolean mInitialized;
private boolean mAeAwbLock;
private Matrix mMatrix;
private SoundPlayer mSoundPlayerOK;
private SoundPlayer mSoundPlayerFalse;
private RelativeLayout focusLayout;
private RotateLayout mFocusIndicatorRotateLayout;
private RotateLayout mMeteringIndicatorRotateLayout;
private FocusIndicatorView mFocusIndicator;
private ImageView mMeteringIndicator;
private int mPreviewWidth;
private int mPreviewHeight;
private List<Area> mFocusArea; // focus
// area
// in
// driver
// format
private List<Area> mMeteringArea; // metering
// area
// in
// driver
// format
private int mFocusMode;
private int mDefaultFocusMode;
private int mOverrideFocusMode = -1;
private SharedPreferences mPreferences;
private Handler mHandler;
// Camera capabilities
private boolean mFocusAreaSupported = false;
private boolean mMeteringAreaSupported = false;
private boolean mFocusDisabled = false;
private boolean mFocusLocked = false;
private boolean isDoubleClick = false;
private int preferenceFocusMode = -1;
private boolean splitMode = false;
private boolean exposureControlEnaled = false;
private class MainHandler extends Handler
{
@Override
public void handleMessage(Message msg)
{
if (msg.what == RESET_TOUCH_FOCUS && !currentTouch)
cancelAutoFocus();
else if (msg.what == START_TOUCH_FOCUS)
{
lastEvent.setAction(MotionEvent.ACTION_UP);
delayedFocus = true;
cancelAutoFocus();
onTouchAreas(lastEvent);
//lastEvent.recycle();
}
}
}
public FocusVFPlugin()
{
super("com.almalence.plugins.focusvf", R.xml.preferences_vf_focus, 0, 0, null);
mHandler = new MainHandler();
mMatrix = new Matrix();
}
@Override
public void onCreate()
{
View v = LayoutInflater.from(ApplicationScreen.getMainContext()).inflate(R.layout.plugin_vf_focus_layout, null);
focusLayout = (RelativeLayout) v.findViewById(R.id.focus_layout);
RelativeLayout.LayoutParams viewLayoutParams = new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.FILL_PARENT);
viewLayoutParams.addRule(RelativeLayout.CENTER_IN_PARENT);
mFocusIndicatorRotateLayout = (RotateLayout) v.findViewById(R.id.focus_indicator_rotate_layout);
mMeteringIndicatorRotateLayout = (RotateLayout) v.findViewById(R.id.metering_indicator_rotate_layout);
mFocusIndicatorRotateLayout.setOnTouchListener(new OnTouchListener()
{
@Override
public boolean onTouch(View v, MotionEvent event)
{
if (!mFocusIndicator.isVisible()) {
return false;
}
updateCurrentTouch(event);
if (splitMode)
{
onTouchFocusArea(event);
return true;
} else
{
// Check if it's double click
if (event.getAction() == MotionEvent.ACTION_UP)
{
splitMode = true;
lastTouchTime1 = lastTouchTime2;
lastTouchTime2 = System.currentTimeMillis();
if (lastTouchTime2 - lastTouchTime1 < 1000)
{
isDoubleClick = true;
splitMode = false;
} else
{
isDoubleClick = false;
}
onTouchFocusAndMeteringArea(event);
}
return true;
}
}
});
mMeteringIndicatorRotateLayout.setOnTouchListener(new OnTouchListener()
{
@Override
public boolean onTouch(View v, MotionEvent event)
{
updateCurrentTouch(event);
if (event.getAction() == MotionEvent.ACTION_MOVE)
splitMode = true;
// Check if it's double click
if (event.getAction() == MotionEvent.ACTION_UP && (!splitMode || CameraController.getFocusMode() == CameraParameters.MF_MODE))
{
lastTouchTime1 = lastTouchTime2;
lastTouchTime2 = System.currentTimeMillis();
if (lastTouchTime2 - lastTouchTime1 < 1000)
{
if (ApplicationScreen.instance.isShotOnTap() == 2 && (mState == STATE_SUCCESS || CameraController.getFocusMode() == CameraParameters.MF_MODE))
{
String modeID = PluginManager.getInstance().getActiveMode().modeID;
if (!modeID.equals("video") && !currentTouch)
{
ApplicationScreen.getGUIManager().onHardwareShutterButtonPressed();
}
isDoubleClick = false;
splitMode = false;
}
else {
isDoubleClick = true;
splitMode = false;
}
} else
{
isDoubleClick = false;
}
}
onTouchMeteringArea(event);
return true;
}
});
mFocusIndicator = (FocusIndicatorView) mFocusIndicatorRotateLayout.findViewById(R.id.focus_indicator);
mMeteringIndicator = (ImageView) mMeteringIndicatorRotateLayout.findViewById(R.id.metering_indicator);
resetTouchFocus();
mPreferences = PreferenceManager.getDefaultSharedPreferences(ApplicationScreen.getMainContext());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
{
mDefaultFocusMode = CameraParameters.AF_MODE_CONTINUOUS_PICTURE;
} else
{
mDefaultFocusMode = CameraParameters.AF_MODE_AUTO;
}
}
private void updateCurrentTouch(MotionEvent event)
{
if (event.getAction() == MotionEvent.ACTION_DOWN)
{
currentTouch = true;
}
if (event.getAction() == MotionEvent.ACTION_UP)
{
currentTouch = false;
}
}
@Override
public void onStart()
{
mState = STATE_IDLE;
updateFocusUI();
CameraController.setFocusState(CameraController.FOCUS_STATE_IDLE);
}
@Override
public void onStop()
{
// cancelAutoFocus();
mState = STATE_INACTIVE;
updateFocusUI();
CameraController.setFocusState(CameraController.FOCUS_STATE_IDLE);
ApplicationScreen.getGUIManager().removeViews(focusLayout, R.id.specialPluginsLayout);
}
@Override
public void onGUICreate()
{
ApplicationScreen.getGUIManager().removeViews(focusLayout, R.id.specialPluginsLayout);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.FILL_PARENT);
params.addRule(RelativeLayout.CENTER_IN_PARENT);
((RelativeLayout) ApplicationScreen.instance.findViewById(R.id.specialPluginsLayout)).addView(this.focusLayout,
params);
this.focusLayout.setLayoutParams(params);
this.focusLayout.requestLayout();
}
@Override
public void onResume()
{
exposureControlEnaled = PreferenceManager.getDefaultSharedPreferences(ApplicationScreen.getMainContext()).getBoolean("Pref_EnableExposureMetering", true);
}
@Override
public void onPause()
{
releaseSoundPlayer();
removeMessages();
}
@Override
public void onCameraParametersSetup()
{
// replace here with [CF] mode as default.
// Also, check if [CF] is available, and if not - set [AF], if [AF] is
// not available - set first available
preferenceFocusMode = ApplicationScreen.instance.getFocusModePref(ApplicationScreen.sDefaultFocusValue);
int[] supportedFocusModes = CameraController.getSupportedFocusModes();
if (supportedFocusModes != null && supportedFocusModes.length > 0)
{
if (!CameraController.isModeAvailable(supportedFocusModes, preferenceFocusMode)
&& preferenceFocusMode != CameraParameters.MF_MODE
&& preferenceFocusMode != CameraParameters.AF_MODE_LOCK)
{
if (CameraController.isModeAvailable(supportedFocusModes, CameraParameters.AF_MODE_AUTO))
preferenceFocusMode = CameraParameters.AF_MODE_AUTO;
else
preferenceFocusMode = supportedFocusModes[0];
}
}
initializeParameters();
initialize(CameraController.isFrontCamera(), 90);
initializeSoundPlayers(ApplicationScreen.getAppResources().openRawResourceFd(R.raw.plugin_vf_focus_ok), ApplicationScreen
.getAppResources().openRawResourceFd(R.raw.plugin_vf_focus_false));
cancelAutoFocus();
// Set the length of focus indicator according to preview frame size.
int len = Math.min(mPreviewWidth, mPreviewHeight) / 25;
ViewGroup.LayoutParams layout = mFocusIndicator.getLayoutParams();
layout.width = (int) (len * ApplicationScreen.getAppResources().getInteger(R.integer.focusIndicator_cropFactor));
layout.height = (int) (len * ApplicationScreen.getAppResources().getInteger(R.integer.focusIndicator_cropFactor));
mFocusIndicator.requestLayout();
layout = mMeteringIndicator.getLayoutParams();
layout.width = (int) (len * ApplicationScreen.getAppResources().getInteger(R.integer.focusIndicator_cropFactor));
layout.height = (int) (len * ApplicationScreen.getAppResources().getInteger(R.integer.focusIndicator_cropFactor));
mMeteringIndicator.requestLayout();
}
/*
*
*
* FOCUS MANAGER`S FUNCTIONALITY
*/
// This has to be initialized before initialize().
public void initializeParameters()
{
mFocusAreaSupported = (CameraController.getMaxFocusAreasSupported() > 0 && isSupported(
CameraParameters.AF_MODE_AUTO, CameraController.getSupportedFocusModes()));
mMeteringAreaSupported = CameraController.getMaxMeteringAreasSupported() > 0;
}
public void initialize(boolean mirror, int displayOrientation)
{
mPreviewWidth = ApplicationScreen.getPreviewSurfaceLayoutWidth();
mPreviewHeight = ApplicationScreen.getPreviewSurfaceLayoutHeight();
Matrix matrix = new Matrix();
Util.prepareMatrix(matrix, mirror, CameraController.getSensorOrientation(mirror) , mPreviewWidth, mPreviewHeight);
// In face detection, the matrix converts the driver coordinates to UI
// coordinates. In tap focus, the inverted matrix converts the UI
// coordinates to driver coordinates.
matrix.invert(mMatrix);
mInitialized = true;
}
@Override
public void onShutterClick()
{
if (needAutoFocusCall() && !focusOnShutterDisabled())
{
if (mState == STATE_IDLE
&& !(preferenceFocusMode == CameraParameters.AF_MODE_CONTINUOUS_PICTURE || preferenceFocusMode == CameraParameters.AF_MODE_CONTINUOUS_VIDEO)
&& !ApplicationScreen.instance.getAutoFocusLock())
{
if (preferenceFocusMode == CameraParameters.AF_MODE_CONTINUOUS_PICTURE
|| preferenceFocusMode == CameraParameters.AF_MODE_CONTINUOUS_VIDEO)
{
CameraController.setCameraFocusMode(CameraParameters.AF_MODE_AUTO);
}
setFocusParameters();
setMeteringParameters();
autoFocus();
}
else if (mState == STATE_FAIL)
ApplicationScreen.getGUIManager().lockControls = false;
}
else
{
int focusMode = getFocusMode();
if(focusMode == CameraParameters.AF_MODE_CONTINUOUS_PICTURE &&
(CameraController.isGalaxyS6 || CameraController.isGalaxyS5 || CameraController.isGalaxyNote4))
{
final int[] supported_focus = CameraController.getSupportedFocusModes();
int afMode = -1;
if (CameraController.isModeAvailable(supported_focus, CameraParameters.AF_MODE_AUTO))
afMode = CameraParameters.AF_MODE_AUTO;
else if (CameraController.isModeAvailable(supported_focus, CameraParameters.AF_MODE_MACRO))
afMode = CameraParameters.AF_MODE_MACRO;
else
afMode = supported_focus[0];
CameraController.setCameraFocusMode(afMode);
ApplicationScreen.instance.setAutoFocusLock(true);
}
}
}
@Override
public void onFocusButtonClick()
{
if (needAutoFocusCall() && !focusOnShutterDisabled())
{
cancelAutoFocus();
resetTouchFocus();
autoFocus();
}
}
public void setFocusParameters()
{
if (mFocusAreaSupported || CameraController.isRemoteCamera())
CameraController.setCameraFocusAreas(getFocusAreas());
}
public void setMeteringParameters()
{
if (mMeteringAreaSupported)
{
// Use the same area for focus and metering.
List<Area> area = getMeteringAreas();
if (area != null)
CameraController.setCameraMeteringAreas(area);
}
}
@Override
public void onAutoFocusMoving(boolean start)
{
if (!splitMode)
return;
if (start)
{
mState = STATE_FOCUSING;
} else
{
mState = STATE_SUCCESS;
}
updateFocusUI();
}
@Override
public void onAutoFocus(boolean focused)
{
if (mState == STATE_FOCUSING_SNAP_ON_FINISH)
{
// Take the picture no matter focus succeeds or fails. No need
// to play the AF sound if we're about to play the shutter
// sound.
if (focused)
{
mState = STATE_SUCCESS;
} else
{
mState = STATE_FAIL;
ApplicationScreen.getGUIManager().lockControls = false;
}
updateFocusUI();
} else if (mState == STATE_FOCUSING)
{
// This happens when (1) user is half-pressing the focus key or
// (2) touch focus is triggered. Play the focus tone. Do not
// take the picture now.
if (focused)
{
mState = STATE_SUCCESS;
/*
* Note: we are always using full-focus scan, even in continuous
* modes
*
* // Do not play the sound in continuous autofocus mode. It
* does // not do a full scan. The focus callback arrives before
* doSnap // so the state is always STATE_FOCUSING. if
* (!Parameters.FOCUS_MODE_CONTINUOUS_PICTURE.equals(mFocusMode)
* && mSoundPlayerOK != null)
*/
if (mSoundPlayerOK != null && !splitMode && !currentTouch)
if (!ApplicationScreen.instance.isShutterSoundEnabled() && !ApplicationScreen.getPluginManager().muteSounds())
mSoundPlayerOK.play();
// With enabled preference 'Shot on tap' perform shutter button
// click after success focusing.
String modeID = PluginManager.getInstance().getActiveMode().modeID;
if (ApplicationScreen.instance.isShotOnTap() == 1 && !modeID.equals("video") && !splitMode && !currentTouch)
ApplicationScreen.getGUIManager().onHardwareShutterButtonPressed();
if (ApplicationScreen.instance.isShotOnTap() == 2 && !modeID.equals("video") && !splitMode && !currentTouch)
{
if (isDoubleClick)
{
ApplicationScreen.getGUIManager().onHardwareShutterButtonPressed();
isDoubleClick = false;
}
}
} else
{
if (mSoundPlayerFalse != null)
if (!ApplicationScreen.instance.isShutterSoundEnabled() && !PluginManager.getInstance().muteSounds())
mSoundPlayerFalse.play();
mState = STATE_FAIL;
}
updateFocusUI();
if (!splitMode)
mHandler.sendEmptyMessageDelayed(RESET_TOUCH_FOCUS, RESET_TOUCH_FOCUS_DELAY);
// If this is triggered by touch focus, cancel focus after a
// while.
} else if (mState == STATE_IDLE)
{
// User has released the focus key before focus completes.
// Do nothing.
}
}
private static float X = 0;
private static float Y = 0;
private static boolean focusCanceled = false;
private static boolean delayedFocus = false;
private static MotionEvent lastEvent = null;
private static boolean currentTouch = false;
@Override
public boolean onTouch(View view, MotionEvent e)
{
if (CameraController.isRemoteCamera())
{
if (e.getAction() == MotionEvent.ACTION_UP)
{
onTouchAreas(e);
}
return true;
}
updateCurrentTouch(e);
if (splitMode && e.getAction() == MotionEvent.ACTION_DOWN)
{
ApplicationScreen.instance.setCameraMeteringMode(ApplicationScreen.getMeteringMode());
splitMode = false;
return true;
}
if (splitMode)
{
return true;
}
// Check if it's double click
if (e.getAction() == MotionEvent.ACTION_UP
&& (
(CameraController.getFocusMode() == CameraParameters.MF_MODE && ApplicationScreen.getMeteringMode() == CameraParameters.meteringModeManual)
|| mFocusIndicator.isVisible()
|| (CameraController.getFocusMode() == CameraParameters.MF_MODE && mMeteringIndicatorRotateLayout.getVisibility() == View.VISIBLE)))
{
lastTouchTime1 = lastTouchTime2;
lastTouchTime2 = System.currentTimeMillis();
if (lastTouchTime2 - lastTouchTime1 < 1000)
{
isDoubleClick = true;
// If shot on double click
if (ApplicationScreen.instance.isShotOnTap() == 2)
{
// Cancel delayed focus, which was created by second click
mHandler.removeMessages(START_TOUCH_FOCUS);
// If state is Focused start capture
if (mState == STATE_SUCCESS || CameraController.getFocusMode() == CameraParameters.MF_MODE)
{
String modeID = PluginManager.getInstance().getActiveMode().modeID;
if (!modeID.equals("video") && !currentTouch)
{
ApplicationScreen.getGUIManager().onHardwareShutterButtonPressed();
isDoubleClick = false;
}
}
return true;
}
} else
{
isDoubleClick = false;
}
}
// Not handle touch event if no need of autoFocus and refuse 'shot on
// tap' in video mode.
if (!mInitialized
|| mState == STATE_FOCUSING_SNAP_ON_FINISH
|| mState == STATE_INACTIVE
|| mFocusDisabled
|| !CameraController.isFocusModeSupported()
|| (!(needAutoFocusCall() || isContinuousFocusMode() || ApplicationScreen.getMeteringMode() != CameraParameters.meteringModeManual) && !(ApplicationScreen.instance.isShotOnTap() > 0 && !PluginManager
.getInstance().getActiveMode().modeID.equals("video"))))
return false;
// Let users be able to cancel previous touch focus.
if ((mState == STATE_FOCUSING) && !delayedFocus && ApplicationScreen.instance.isShotOnTap() != 2)
{
focusCanceled = true;
cancelAutoFocus();
int fm = CameraController.getFocusMode();
if ((preferenceFocusMode == CameraParameters.AF_MODE_CONTINUOUS_PICTURE || preferenceFocusMode == CameraParameters.AF_MODE_CONTINUOUS_VIDEO)
&& fm != CameraParameters.AF_MODE_UNSUPPORTED
&& preferenceFocusMode != CameraController.getFocusMode()
&& preferenceFocusMode != CameraParameters.MF_MODE)
{
CameraController.setCameraFocusMode(preferenceFocusMode);
} else if (CameraController.isGalaxyNote3 && preferenceFocusMode != CameraParameters.MF_MODE)
// Kind of hack to
// prevent Note 3 of
// permanent 'auto focus
// failed' state
{
CameraController.setCameraFocusMode(CameraParameters.AF_MODE_CONTINUOUS_PICTURE);
CameraController.setCameraFocusMode(preferenceFocusMode);
}
return true;
}
switch (e.getAction())
{
case MotionEvent.ACTION_DOWN:
focusCanceled = false;
delayedFocus = false;
X = e.getX();
Y = e.getY();
lastEvent = MotionEvent.obtain(e);
mHandler.sendEmptyMessageDelayed(START_TOUCH_FOCUS, START_TOUCH_FOCUS_DELAY);
return true;
case MotionEvent.ACTION_MOVE:
{
float difX = e.getX();
float difY = e.getY();
if ((Math.abs(difX - X) > 50 || Math.abs(difY - Y) > 50) && !focusCanceled)
{
focusCanceled = true;
cancelAutoFocus();
mHandler.removeMessages(START_TOUCH_FOCUS);
return true;
} else
return true;
}
case MotionEvent.ACTION_UP:
mHandler.removeMessages(START_TOUCH_FOCUS);
lastTouchTime1 = lastTouchTime2;
lastTouchTime2 = System.currentTimeMillis();
if (focusCanceled || delayedFocus)
return true;
break;
default:
break;
}
onTouchFocusAndMeteringArea(e);
return true;
}
public void onTouchFocusArea(MotionEvent e)
{
if (!mFocusAreaSupported)
return;
int xRaw = (int) e.getRawX();
int yRaw = (int) e.getRawY();
if (e.getPointerCount() > 1)
{
final int location[] = { 0, 0 };
mFocusIndicatorRotateLayout.getLocationOnScreen(location);
xRaw = (int) e.getX(0) + location[0];
yRaw = (int) e.getY(0) + location[1];
}
// Initialize variables.
int focusWidth = mFocusIndicatorRotateLayout.getWidth();
int focusHeight = mFocusIndicatorRotateLayout.getHeight();
int previewWidth = mPreviewWidth;
int previewHeight = mPreviewHeight;
int displayWidth = ApplicationScreen.getAppResources().getDisplayMetrics().widthPixels;
int displayHeight = ApplicationScreen.getAppResources().getDisplayMetrics().heightPixels;
int diffWidth = displayWidth - previewWidth;
int diffHeight = displayHeight - previewHeight;
// Initialize variables.
int paramsLayoutHeight = 0;
int xOffset = (focusLayout.getWidth() - previewWidth) / 2;
int yOffset = (focusLayout.getHeight() - previewHeight) / 2;
if (mFocusArea == null)
{
mFocusArea = new ArrayList<Area>();
mFocusArea.add(new Area(new Rect(), 1000));
}
// Use margin to set the metering indicator to the touched area.
RelativeLayout.LayoutParams p = (RelativeLayout.LayoutParams) mFocusIndicatorRotateLayout.getLayoutParams();
int left = Util.clamp(xRaw - focusWidth / 2 + xOffset, diffWidth / 2, (previewWidth - focusWidth + xOffset * 2)
- diffWidth / 2);
int top = Util.clamp(yRaw - focusHeight / 2 + yOffset - diffHeight / 2, 0, previewHeight - focusHeight
+ yOffset * 2);
p.leftMargin = left;
p.topMargin = top;
int[] rules = p.getRules();
rules[RelativeLayout.CENTER_IN_PARENT] = 0;
mFocusIndicatorRotateLayout.setLayoutParams(p);
xRaw = Util.clamp(xRaw - diffWidth, 0, previewWidth);
yRaw = Util.clamp(yRaw - diffHeight, 0, previewHeight);
if (CameraController.getSensorOrientation(CameraController.isFrontCamera()) == 90)
{
int tmpX = xRaw;
xRaw = yRaw;
yRaw = previewWidth - tmpX - 1;
}
else //Sensor 270
{
int tmpX = xRaw;
xRaw = previewHeight - yRaw - 1;
yRaw = tmpX;
}
CameraController.calculateTapArea(focusWidth, focusHeight, 1f, top, left,
ApplicationScreen.getPreviewSurfaceView().getWidth(), ApplicationScreen.getPreviewSurfaceView().getHeight(),
xRaw, yRaw, mMatrix,
mFocusArea.get(0).rect);
// Set the focus area and metering area.
if (mFocusAreaSupported
&& (e.getActionMasked() == MotionEvent.ACTION_UP || e.getActionMasked() == MotionEvent.ACTION_POINTER_UP))
{
setFocusParameters();
int focusMode = CameraController.getFocusMode();
if (focusMode == CameraParameters.AF_MODE_AUTO || focusMode == CameraParameters.AF_MODE_MACRO)
{
// @TODO: This line reset exposure metering area for camera2. Can't figure out, why cancelAutoFocus required here.
//CameraController.cancelAutoFocus();
autoFocus();
} else
{
mState = STATE_FOCUSING;
updateFocusUI();
}
}
mFocusIndicatorRotateLayout.requestLayout();
}
public void onTouchMeteringArea(MotionEvent e)
{
if (!mMeteringAreaSupported || CameraController.isGalaxyNote3)
{
if (e.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN
|| e.getActionMasked() == MotionEvent.ACTION_DOWN)
Toast.makeText(ApplicationScreen.instance, R.string.manual_exposure_unsupported, Toast.LENGTH_SHORT)
.show();
return;
}
if (!exposureControlEnaled)
{
return;
}
int xRaw = (int) e.getRawX();
int yRaw = (int) e.getRawY();
if (e.getPointerCount() > 1)
{
final int location[] = { 0, 0 };
mMeteringIndicatorRotateLayout.getLocationOnScreen(location);
xRaw = (int) e.getX(0) + location[0];
yRaw = (int) e.getY(0) + location[1];
}
int meteringWidth = mMeteringIndicatorRotateLayout.getWidth();
int meteringHeight = mMeteringIndicatorRotateLayout.getHeight();
int previewWidth = mPreviewWidth;
int previewHeight = mPreviewHeight;
int displayWidth = ApplicationScreen.getAppResources().getDisplayMetrics().widthPixels;
int displayHeight = ApplicationScreen.getAppResources().getDisplayMetrics().heightPixels;
int diffWidth = displayWidth - previewWidth;
int diffHeight = displayHeight - previewHeight;
// Initialize variables.
int paramsLayoutHeight = 0;
int xOffset = (focusLayout.getWidth() - previewWidth) / 2;
int yOffset = (focusLayout.getHeight() - previewHeight) / 2;
if (mMeteringArea == null)
{
mMeteringArea = new ArrayList<Area>();
mMeteringArea.add(new Area(new Rect(), 1000));
}
// Use margin to set the metering indicator to the touched area.
RelativeLayout.LayoutParams p = (RelativeLayout.LayoutParams) mMeteringIndicatorRotateLayout.getLayoutParams();
int left = Util.clamp(xRaw - meteringWidth / 2 + xOffset, diffWidth / 2,
(previewWidth - meteringWidth + xOffset * 2) - diffWidth / 2);
int top = Util.clamp(yRaw - meteringHeight / 2 + yOffset - diffHeight / 2, 0, previewHeight - meteringHeight
+ yOffset * 2);
p.leftMargin = left;
p.topMargin = top;
mMeteringIndicatorRotateLayout.setLayoutParams(p);
xRaw = Util.clamp(xRaw - diffWidth, 0, previewWidth);
yRaw = Util.clamp(yRaw - diffHeight, 0, previewHeight);
if (CameraController.getSensorOrientation(CameraController.isFrontCamera()) == 90)
{
int tmpX = xRaw;
xRaw = yRaw;
yRaw = previewWidth - tmpX - 1;
}
else //Sensor 270
{
int tmpX = xRaw;
xRaw = previewHeight - yRaw - 1;
yRaw = tmpX;
}
CameraController.calculateTapArea(meteringWidth, meteringHeight, 1f, top, left,
ApplicationScreen.getPreviewSurfaceView().getWidth(), ApplicationScreen.getPreviewSurfaceView().getHeight(),
xRaw, yRaw, mMatrix,
mMeteringArea.get(0).rect);
if (e.getActionMasked() == MotionEvent.ACTION_POINTER_UP || e.getActionMasked() == MotionEvent.ACTION_UP)
{
setMeteringParameters();
mHandler.removeMessages(RESET_TOUCH_FOCUS);
mHandler.sendEmptyMessageDelayed(RESET_TOUCH_FOCUS, RESET_TOUCH_FOCUS_DELAY);
}
mMeteringIndicatorRotateLayout.requestLayout();
}
public void onTouchFocusAndMeteringArea(MotionEvent e)
{
if (!mFocusAreaSupported || e.getAction() != MotionEvent.ACTION_UP )
return;
int xRaw = (int) e.getRawX();
int yRaw = (int) e.getRawY();
// Initialize variables.
int focusWidth = mFocusIndicatorRotateLayout.getWidth();
int focusHeight = mFocusIndicatorRotateLayout.getHeight();
int previewWidth = mPreviewWidth;
int previewHeight = mPreviewHeight;
int displayWidth = ApplicationScreen.getAppResources().getDisplayMetrics().widthPixels;
int displayHeight = ApplicationScreen.getAppResources().getDisplayMetrics().heightPixels;
int diffWidth = displayWidth - previewWidth;
int diffHeight = displayHeight - previewHeight;
// Initialize variables.
int xOffset = (focusLayout.getWidth() - previewWidth) / 2;
int yOffset = (focusLayout.getHeight() - previewHeight) / 2;
if (mFocusArea == null)
{
mFocusArea = new ArrayList<Area>();
mFocusArea.add(new Area(new Rect(), 1000));
}
if (mMeteringArea == null)
{
mMeteringArea = new ArrayList<Area>();
mMeteringArea.add(new Area(new Rect(), 1000));
}
// Use margin to set the metering indicator to the touched area.
RelativeLayout.LayoutParams fp = (RelativeLayout.LayoutParams) mFocusIndicatorRotateLayout.getLayoutParams();
int left = Util.clamp(xRaw - focusWidth / 2 + xOffset, diffWidth / 2, (previewWidth - focusWidth + xOffset * 2)
- diffWidth / 2);
int top = Util.clamp(yRaw - focusHeight / 2 + yOffset - diffHeight / 2, 0, previewHeight - focusHeight
+ yOffset * 2);
fp.leftMargin = left;
fp.topMargin = top;
int[] frules = fp.getRules();
frules[RelativeLayout.CENTER_IN_PARENT] = 0;
mFocusIndicatorRotateLayout.setLayoutParams(fp);
RelativeLayout.LayoutParams mp = (RelativeLayout.LayoutParams) mMeteringIndicatorRotateLayout.getLayoutParams();
mp.leftMargin = left;
mp.topMargin = top;
int[] mrules = mp.getRules();
mrules[RelativeLayout.CENTER_IN_PARENT] = 0;
mMeteringIndicatorRotateLayout.setLayoutParams(mp);
if(!mMeteringAreaSupported)
mMeteringIndicatorRotateLayout.setVisibility(View.GONE);
xRaw = Util.clamp(xRaw - diffWidth, 0, previewWidth);
yRaw = Util.clamp(yRaw - diffHeight, 0, previewHeight);
//TODO: Logic of coordinate's swapping must be based on sensor orientation not on device model!
if (CameraController.getSensorOrientation(CameraController.isFrontCamera()) == 90)
{
int tmpX = xRaw;
xRaw = yRaw;
yRaw = previewWidth - tmpX - 1;
}
else //Sensor 270
{
int tmpX = xRaw;
xRaw = previewHeight - yRaw - 1;
yRaw = tmpX;
}
CameraController.calculateTapArea(focusWidth, focusHeight, 1f, top, left,
ApplicationScreen.getPreviewSurfaceView().getWidth(), ApplicationScreen.getPreviewSurfaceView().getHeight(),
xRaw, yRaw, mMatrix,
mFocusArea.get(0).rect);
if (exposureControlEnaled && ApplicationScreen.getMeteringMode() != -1 && (ApplicationScreen.getMeteringMode() == CameraParameters.meteringModeSpot || CameraController.getFocusMode() == CameraParameters.MF_MODE))
CameraController.calculateTapArea(focusWidth, focusHeight, 1f, top, left,
ApplicationScreen.getPreviewSurfaceView()
.getWidth(), ApplicationScreen.getPreviewSurfaceView().getHeight(),
xRaw, yRaw, mMatrix,
mMeteringArea.get(0).rect);
else
mMeteringArea = null;
// Set the focus area and metering area.
if ((mFocusAreaSupported && needAutoFocusCall() && (e.getAction() == MotionEvent.ACTION_UP)) || (e.getAction() == MotionEvent.ACTION_UP && CameraController.isRemoteCamera()))
{
CameraController.cancelAutoFocus();
if (preferenceFocusMode == CameraParameters.AF_MODE_CONTINUOUS_PICTURE
|| preferenceFocusMode == CameraParameters.AF_MODE_CONTINUOUS_VIDEO)
{
CameraController.setCameraFocusMode(CameraParameters.AF_MODE_AUTO);
//If call autoFocus right after set new focus mode
//auto focus routine may never been finished
//so we have to wait little time to perform autoFocus
new CountDownTimer(150,150)
{
@Override
public void onFinish()
{
setFocusParameters();
setMeteringParameters();
autoFocus();
}
@Override
public void onTick(long millisUntilFinished)
{
// TODO Auto-generated method stub
}
}.start();
}
else
{
setFocusParameters();
setMeteringParameters();
autoFocus();
}
} else if (mMeteringArea != null && ApplicationScreen.getMeteringMode() != CameraParameters.meteringModeManual)
{
setMeteringParameters();
updateFocusUI();
mHandler.removeMessages(RESET_TOUCH_FOCUS);
mHandler.sendEmptyMessageDelayed(RESET_TOUCH_FOCUS, RESET_TOUCH_FOCUS_DELAY);
if (e.getAction() == MotionEvent.ACTION_UP && ApplicationScreen.instance.isShotOnTap() == 1
&& !PluginManager.getInstance().getActiveMode().modeID.equals("video") && !currentTouch)
ApplicationScreen.getGUIManager().onHardwareShutterButtonPressed();
} else if (e.getAction() == MotionEvent.ACTION_UP && ApplicationScreen.instance.isShotOnTap() == 1
&& !PluginManager.getInstance().getActiveMode().modeID.equals("video") && !currentTouch)
{
ApplicationScreen.getGUIManager().onHardwareShutterButtonPressed();
} else if (e.getAction() == MotionEvent.ACTION_UP && ApplicationScreen.instance.isShotOnTap() == 2
&& !PluginManager.getInstance().getActiveMode().modeID.equals("video") && !currentTouch)
{
if (isDoubleClick)
{
ApplicationScreen.getGUIManager().onHardwareShutterButtonPressed();
isDoubleClick = false;
}
} else if (e.getAction() == MotionEvent.ACTION_UP)
{ // Just show the indicator in all other cases.
autoFocus();
// updateFocusUI();
// Reset the metering area in 3 seconds.
mHandler.removeMessages(RESET_TOUCH_FOCUS);
mHandler.sendEmptyMessageDelayed(RESET_TOUCH_FOCUS, RESET_TOUCH_FOCUS_DELAY);
}
mFocusIndicatorRotateLayout.requestLayout();
}
//Probably is used only for remote Sony camera
public void onTouchAreas(MotionEvent e)
{
// Initialize variables.
int x = Math.round(e.getX());
int y = Math.round(e.getY());
int focusWidth = mFocusIndicatorRotateLayout.getWidth();
int focusHeight = mFocusIndicatorRotateLayout.getHeight();
int previewWidth = mPreviewWidth;
int previewHeight = mPreviewHeight;
int displayWidth = ApplicationScreen.getAppResources().getDisplayMetrics().widthPixels;
int diffWidth = displayWidth - previewWidth;
int paramsLayoutHeight = 0;
int xOffset = (focusLayout.getWidth() - previewWidth) / 2;
int yOffset = (focusLayout.getHeight() - previewHeight) / 2;
if (mFocusArea == null)
{
mFocusArea = new ArrayList<Area>();
mFocusArea.add(new Area(new Rect(), 1000));
}
if (mMeteringArea == null)
{
mMeteringArea = new ArrayList<Area>();
mMeteringArea.add(new Area(new Rect(), 1000));
}
// Convert the coordinates to driver format.
// AE area is bigger because exposure is sensitive and
// easy to over- or underexposure if area is too small.
calculateTapArea(focusWidth, focusHeight, 1f, x, y, ApplicationScreen.getPreviewSurfaceView().getWidth(), ApplicationScreen
.getPreviewSurfaceView().getHeight(), mFocusArea.get(0).rect);
if (ApplicationScreen.getMeteringMode() != -1 && ApplicationScreen.getMeteringMode() == CameraParameters.meteringModeSpot)
calculateTapArea(20 + (CameraController.isNexus6 ? focusWidth : 0), 20 + (CameraController.isNexus6 ? focusHeight : 0), 1f, x, y, ApplicationScreen
.getPreviewSurfaceView().getWidth(), ApplicationScreen.getPreviewSurfaceView().getHeight(),
mMeteringArea.get(0).rect);
else
mMeteringArea = null;
if (mFocusAreaSupported)
{
// Use margin to set the focus indicator to the touched area.
RelativeLayout.LayoutParams p = (RelativeLayout.LayoutParams) mFocusIndicatorRotateLayout.getLayoutParams();
int left = Util.clamp(x - focusWidth / 2 + xOffset, diffWidth / 2,
(previewWidth - focusWidth + xOffset * 2) - diffWidth / 2);
int top = Util.clamp(y - focusHeight / 2 + yOffset, paramsLayoutHeight / 2,
(previewHeight - focusHeight + yOffset * 2) - paramsLayoutHeight / 2);
p.setMargins(left, top, 0, 0);
// Disable "center" rule because we no longer want to put it in the
// center.
int[] rules = p.getRules();
rules[RelativeLayout.CENTER_IN_PARENT] = 0;
mFocusIndicatorRotateLayout.requestLayout();
}
// Set the focus area and metering area.
if (mFocusAreaSupported && needAutoFocusCall() && (e.getAction() == MotionEvent.ACTION_UP))
{
CameraController.cancelAutoFocus();
if (preferenceFocusMode == CameraParameters.AF_MODE_CONTINUOUS_PICTURE
|| preferenceFocusMode == CameraParameters.AF_MODE_CONTINUOUS_VIDEO)
{
CameraController.setCameraFocusMode(CameraParameters.AF_MODE_AUTO);
}
setFocusParameters();
setMeteringParameters();
autoFocus();
} else if (e.getAction() == MotionEvent.ACTION_UP && ApplicationScreen.instance.isShotOnTap() == 1
&& !PluginManager.getInstance().getActiveMode().modeID.equals("video"))
{
ApplicationScreen.getGUIManager().onHardwareShutterButtonPressed();
} else if (e.getAction() == MotionEvent.ACTION_UP && ApplicationScreen.instance.isShotOnTap() == 2
&& !PluginManager.getInstance().getActiveMode().modeID.equals("video"))
{
if (isDoubleClick)
{
ApplicationScreen.getGUIManager().onHardwareShutterButtonPressed();
isDoubleClick = false;
}
} else
{ // Just show the indicator in all other cases.
autoFocus();
// Reset the metering area in 3 seconds.
mHandler.removeMessages(RESET_TOUCH_FOCUS);
mHandler.sendEmptyMessageDelayed(RESET_TOUCH_FOCUS, RESET_TOUCH_FOCUS_DELAY);
}
}
public void onPreviewStarted()
{
mState = STATE_IDLE;
CameraController.setFocusState(CameraController.FOCUS_STATE_IDLE);
}
public void onPreviewStopped()
{
mState = STATE_IDLE;
resetTouchFocus();
// If auto focus was in progress, it would have been canceled.
updateFocusUI();
CameraController.setFocusState(CameraController.FOCUS_STATE_IDLE);
}
public void onCameraReleased()
{
onPreviewStopped();
}
private void autoFocus()
{
if (CameraController.autoFocus())
{
mState = STATE_FOCUSING;
updateFocusUI();
mHandler.removeMessages(RESET_TOUCH_FOCUS);
}
}
private void cancelAutoFocus()
{
// Note: CameraController.getFocusMode(); will return
// 'FOCUS_MODE_AUTO' if actual
// mode is in fact FOCUS_MODE_CONTINUOUS_PICTURE or
// FOCUS_MODE_CONTINUOUS_VIDEO
int fm = CameraController.getFocusMode();
if (fm != CameraParameters.AF_MODE_UNSUPPORTED)
{
if (fm != preferenceFocusMode && preferenceFocusMode != CameraParameters.MF_MODE
&& preferenceFocusMode != CameraParameters.AF_MODE_LOCK)
{
CameraController.cancelAutoFocus();
CameraController.setCameraFocusMode(preferenceFocusMode);
}
}
// Reset the tap area before calling mListener.cancelAutofocus.
// Otherwise, focus mode stays at auto and the tap area passed to the
// driver is not reset.
CameraController.setCameraFocusAreas(null);
ApplicationScreen.instance.setCameraMeteringMode(ApplicationScreen.getMeteringMode());
resetTouchFocus();
mState = STATE_IDLE;
CameraController.setFocusIdle();
updateFocusUI();
mHandler.removeMessages(RESET_TOUCH_FOCUS);
}
public void initializeSoundPlayers(AssetFileDescriptor fd_ok, AssetFileDescriptor fd_false)
{
mSoundPlayerOK = new SoundPlayer(ApplicationScreen.getMainContext(), fd_ok);
mSoundPlayerFalse = new SoundPlayer(ApplicationScreen.getMainContext(), fd_false);
}
public void releaseSoundPlayer()
{
if (mSoundPlayerOK != null)
{
mSoundPlayerOK.release();
mSoundPlayerOK = null;
}
if (mSoundPlayerFalse != null)
{
mSoundPlayerFalse.release();
mSoundPlayerFalse = null;
}
}
// This can only be called after mParameters is initialized.
public int getFocusMode()
{
if (mOverrideFocusMode != CameraParameters.AF_MODE_UNSUPPORTED)
return mOverrideFocusMode;
if (mFocusAreaSupported && mFocusArea != null)
mFocusMode = CameraParameters.AF_MODE_AUTO;
else
mFocusMode = ApplicationScreen.instance.getFocusModePref(mDefaultFocusMode);
if (!isSupported(mFocusMode, CameraController.getSupportedFocusModes()))
{
// For some reasons, the driver does not support the current
// focus mode. Fall back to auto.
if (isSupported(CameraParameters.AF_MODE_AUTO, CameraController.getSupportedFocusModes()))
mFocusMode = CameraParameters.AF_MODE_AUTO;
else
mFocusMode = CameraController.getFocusMode();
}
return mFocusMode;
}
public List<Area> getFocusAreas()
{
return mFocusArea;
}
public List<Area> getMeteringAreas()
{
return mMeteringArea;
}
public void updateFocusUI()
{
if (!mInitialized || !mFocusSupported)
return;
FocusIndicator focusIndicator = mFocusIndicator;
if (mState == STATE_IDLE || mState == STATE_INACTIVE)
{
if (mFocusArea == null) {
focusIndicator.clear();
if (mMeteringArea == null || !mMeteringAreaSupported)
{
mMeteringIndicatorRotateLayout.setVisibility(View.GONE);
}
else {
mMeteringIndicatorRotateLayout.setVisibility(View.VISIBLE);
}
}
else
{
// Users touch on the preview and the indicator represents the
// metering area. Either focus area is not supported or
// autoFocus call is not required.
focusIndicator.showStart();
mFocusIndicatorRotateLayout.setVisibility(View.VISIBLE);
mMeteringIndicatorRotateLayout.setVisibility(View.VISIBLE);
}
} else if (mState == STATE_FOCUSING || mState == STATE_FOCUSING_SNAP_ON_FINISH)
{
focusIndicator.showStart();
mFocusIndicatorRotateLayout.setVisibility(View.VISIBLE);
mMeteringIndicatorRotateLayout.setVisibility(View.VISIBLE);
}
else
{
if (mState == STATE_SUCCESS) {
focusIndicator.showSuccess();
mFocusIndicatorRotateLayout.setVisibility(View.VISIBLE);
mMeteringIndicatorRotateLayout.setVisibility(View.VISIBLE);
}
else if (mState == STATE_FAIL) {
focusIndicator.showFail();
mFocusIndicatorRotateLayout.setVisibility(View.VISIBLE);
mMeteringIndicatorRotateLayout.setVisibility(View.VISIBLE);
}
}
if (!exposureControlEnaled || ApplicationScreen.getMeteringMode() == CameraParameters.meteringModeManual || !mMeteringAreaSupported || CameraController.isGalaxyNote3) {
mMeteringIndicatorRotateLayout.setVisibility(View.GONE);
}
if (CameraController.getFocusMode() == CameraParameters.MF_MODE) {
focusIndicator.clear();
}
}
public void resetTouchFocus()
{
if (!mInitialized)
return;
splitMode = false;
// Put focus indicator to the center.
RelativeLayout.LayoutParams p = (RelativeLayout.LayoutParams) mFocusIndicatorRotateLayout.getLayoutParams();
int[] rules = p.getRules();
rules[RelativeLayout.CENTER_IN_PARENT] = RelativeLayout.TRUE;
p.setMargins(0, 0, 0, 0);
// Put exposure indicator to the center.
RelativeLayout.LayoutParams mp = (RelativeLayout.LayoutParams) mMeteringIndicatorRotateLayout.getLayoutParams();
int[] mrules = mp.getRules();
mrules[RelativeLayout.CENTER_IN_PARENT] = RelativeLayout.TRUE;
mp.setMargins(0, 0, 0, 0);
mFocusArea = null;
mMeteringArea = null;
// allow driver to choose whatever it wants for focusing / metering
// without these two lines Continuous focus is not re-enabled on HTC One
int focusMode = getFocusMode();
if ((focusMode == CameraParameters.AF_MODE_CONTINUOUS_PICTURE
|| focusMode == CameraParameters.AF_MODE_CONTINUOUS_VIDEO || focusMode == CameraParameters.AF_MODE_AUTO || focusMode == CameraParameters.AF_MODE_MACRO)
&& mFocusAreaSupported)
{
String modeName = PreferenceManager.getDefaultSharedPreferences(ApplicationScreen.getMainContext()).getString(
"defaultModeName", null);
boolean isVideoRecording = PreferenceManager.getDefaultSharedPreferences(ApplicationScreen.getMainContext())
.getBoolean("videorecording", false);
}
}
public void calculateTapArea(int focusWidth, int focusHeight, float areaMultiple, int x, int y, int previewWidth,
int previewHeight, Rect rect)
{
int areaWidth = (int) (focusWidth * areaMultiple);
int areaHeight = (int) (focusHeight * areaMultiple);
int left = Util.clamp(x - areaWidth / 2, 0, previewWidth - areaWidth);
int top = Util.clamp(y - areaHeight / 2, 0, previewHeight - areaHeight);
int right = Util.clamp(x + areaWidth / 2, areaWidth, previewWidth);
int bottom = Util.clamp(y + areaHeight / 2, areaHeight, previewHeight);
RectF rectF = new RectF(left, top, right, bottom);
mMatrix.mapRect(rectF);
Util.rectFToRect(rectF, rect);
if (rect.left < -1000)
rect.left = -1000;
if (rect.left > 1000)
rect.left = 1000;
if (rect.right < -1000)
rect.right = -1000;
if (rect.right > 1000)
rect.right = 1000;
if (rect.top < -1000)
rect.top = -1000;
if (rect.top > 1000)
rect.top = 1000;
if (rect.bottom < -1000)
rect.bottom = -1000;
if (rect.bottom > 1000)
rect.bottom = 1000;
}
public void calculateTapAreaByTopLeft(int focusWidth, int focusHeight, float areaMultiple, int top, int left,
int previewWidth, int previewHeight, Rect rect)
{
int areaWidth = (int) (focusWidth * areaMultiple);
int areaHeight = (int) (focusHeight * areaMultiple);
int right = Util.clamp(left + areaWidth, areaWidth, previewWidth);
int bottom = Util.clamp(top + areaHeight, areaHeight, previewHeight);
RectF rectF = new RectF(left, top, right, bottom);
mMatrix.mapRect(rectF);
Util.rectFToRect(rectF, rect);
if (rect.left < -1000)
rect.left = -1000;
if (rect.left > 1000)
rect.left = 1000;
if (rect.right < -1000)
rect.right = -1000;
if (rect.right > 1000)
rect.right = 1000;
if (rect.top < -1000)
rect.top = -1000;
if (rect.top > 1000)
rect.top = 1000;
if (rect.bottom < -1000)
rect.bottom = -1000;
if (rect.bottom > 1000)
rect.bottom = 1000;
}
public boolean isFocusCompleted()
{
return mState == STATE_SUCCESS || mState == STATE_FAIL;
}
public void removeMessages()
{
mHandler.removeMessages(RESET_TOUCH_FOCUS);
}
public void overrideFocusMode(int focusMode)
{
mOverrideFocusMode = focusMode;
}
public void setAeAwbLock(boolean lock)
{
mAeAwbLock = lock;
}
public boolean getAeAwbLock()
{
return mAeAwbLock;
}
private static boolean isSupported(int value, int[] supported)
{
boolean isAvailable = false;
if (supported != null)
for (int currMode : supported)
{
if (currMode == value)
{
isAvailable = true;
break;
}
}
return isAvailable;
}
private boolean needAutoFocusCall()
{
int focusMode = getFocusMode();
return !(focusMode == CameraParameters.AF_MODE_INFINITY
|| focusMode == CameraParameters.AF_MODE_FIXED
|| focusMode == CameraParameters.AF_MODE_EDOF // EDOF likely
// needs
// auto-focus
// call
|| focusMode == CameraParameters.AF_MODE_CONTINUOUS_PICTURE
|| focusMode == CameraParameters.AF_MODE_CONTINUOUS_VIDEO || focusMode == CameraParameters.MF_MODE
|| mFocusDisabled || mFocusLocked || !CameraController.isFocusModeSupported());
}
private boolean isContinuousFocusMode()
{
int focusMode = getFocusMode();
return (focusMode == CameraParameters.AF_MODE_CONTINUOUS_PICTURE || focusMode == CameraParameters.AF_MODE_CONTINUOUS_VIDEO);
}
private boolean focusOnShutterDisabled()
{
return PreferenceManager.getDefaultSharedPreferences(ApplicationScreen.getMainContext()).getBoolean(
"ContinuousCapturing", false);
}
public boolean onBroadcast(int arg1, int arg2)
{
if (arg1 == ApplicationInterface.MSG_CONTROL_LOCKED)
{
mFocusDisabled = true;
} else if (arg1 == ApplicationInterface.MSG_CONTROL_UNLOCKED)
{
mFocusDisabled = false;
} else if (arg1 == ApplicationInterface.MSG_FOCUS_LOCKED)
{
mFocusLocked = true;
} else if (arg1 == ApplicationInterface.MSG_FOCUS_UNLOCKED)
{
mFocusLocked = false;
} else if (arg1 == ApplicationInterface.MSG_CAPTURE_FINISHED)
{
mFocusDisabled = false;
cancelAutoFocus();
} else if (arg1 == ApplicationInterface.MSG_FOCUS_CHANGED)
{
int fm = CameraController.getFocusMode();
if (fm != -1)
{
preferenceFocusMode = fm;
cancelAutoFocus();
}
} else if (arg1 == ApplicationInterface.MSG_EXPOSURE_CHANGED)
{
cancelAutoFocus();
} else if (arg1 == ApplicationInterface.MSG_PREVIEW_CHANGED)
{
initialize(CameraController.isFrontCamera(), 90);
}
return false;
}
@Override
public void onCaptureFinished()
{
mFocusDisabled = false;
if (!mFocusLocked)
cancelAutoFocus();
}
}