blob: 14d59c44225f4016ebb429032ac8128de7ab6639 [file] [log] [blame]
Doris Liu6827ce22013-03-12 19:24:28 -07001/*
Doris Liu6432cd62013-06-13 17:20:31 -07002 * Copyright (C) 2012 The Android Open Source Project
Doris Liu6827ce22013-03-12 19:24:28 -07003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.camera;
18
Santhosh Kumar H E6bc53a12013-10-25 13:14:10 +053019import android.content.res.Configuration;
Doris Liu6827ce22013-03-12 19:24:28 -070020import android.graphics.Bitmap;
Doris Liuc3679c02013-08-08 18:08:43 -070021import android.graphics.Color;
Doris Liu6432cd62013-06-13 17:20:31 -070022import android.graphics.Matrix;
Likai Ding40d36372014-11-20 08:00:28 +080023import android.graphics.SurfaceTexture;
Doris Liuc3679c02013-08-08 18:08:43 -070024import android.graphics.drawable.ColorDrawable;
Doris Liu6827ce22013-03-12 19:24:28 -070025import android.hardware.Camera.Parameters;
Doris Liu6432cd62013-06-13 17:20:31 -070026import android.os.Handler;
27import android.os.Message;
Doris Liu6827ce22013-03-12 19:24:28 -070028import android.util.Log;
29import android.view.Gravity;
Doris Liu6827ce22013-03-12 19:24:28 -070030import android.view.SurfaceHolder;
Doris Liu6432cd62013-06-13 17:20:31 -070031import android.view.SurfaceView;
Likai Ding40d36372014-11-20 08:00:28 +080032import android.view.TextureView;
33import android.view.TextureView.SurfaceTextureListener;
Doris Liu6827ce22013-03-12 19:24:28 -070034import android.view.View;
35import android.view.View.OnClickListener;
Doris Liu6432cd62013-06-13 17:20:31 -070036import android.view.View.OnLayoutChangeListener;
Doris Liu6827ce22013-03-12 19:24:28 -070037import android.view.ViewGroup;
Doris Liu6827ce22013-03-12 19:24:28 -070038import android.widget.FrameLayout.LayoutParams;
39import android.widget.ImageView;
40import android.widget.LinearLayout;
Doris Liuc3679c02013-08-08 18:08:43 -070041import android.widget.PopupWindow;
Doris Liu6827ce22013-03-12 19:24:28 -070042import android.widget.TextView;
43
44import com.android.camera.CameraPreference.OnPreferenceChangedListener;
45import com.android.camera.ui.AbstractSettingPopup;
Doris Liu6432cd62013-06-13 17:20:31 -070046import com.android.camera.ui.CameraControls;
47import com.android.camera.ui.CameraRootView;
Angus Konged15d1a2013-08-19 15:06:12 -070048import com.android.camera.ui.ModuleSwitcher;
Doris Liu6827ce22013-03-12 19:24:28 -070049import com.android.camera.ui.PieRenderer;
Doris Liu6827ce22013-03-12 19:24:28 -070050import com.android.camera.ui.RenderOverlay;
51import com.android.camera.ui.RotateLayout;
Likai Ding1e4d9572014-11-20 08:01:08 +080052import com.android.camera.PauseButton.OnPauseButtonListener;
Doris Liu6827ce22013-03-12 19:24:28 -070053import com.android.camera.ui.ZoomRenderer;
Angus Kongb50b5cb2013-08-09 14:55:20 -070054import com.android.camera.util.CameraUtil;
Sachin Shah89d153b2014-08-15 18:36:44 -070055import org.codeaurora.snapcam.R;
Sascha Haeberling638e6f02013-09-18 14:28:51 -070056
Likai Ding1e4d9572014-11-20 08:01:08 +080057import java.util.List;
58
Doris Liu6432cd62013-06-13 17:20:31 -070059public class VideoUI implements PieRenderer.PieListener,
Michael Kolb3bc96b22013-03-12 10:24:42 -070060 PreviewGestures.SingleTapListener,
Doris Liu6432cd62013-06-13 17:20:31 -070061 CameraRootView.MyDisplayListener,
Likai Ding40d36372014-11-20 08:00:28 +080062 SurfaceTextureListener, SurfaceHolder.Callback,
Manikanta Kanamarlapudiae019672014-01-06 14:31:43 +053063 PauseButton.OnPauseButtonListener {
Angus Kong395ee2d2013-07-15 12:42:41 -070064 private static final String TAG = "CAM_VideoUI";
Doris Liu6432cd62013-06-13 17:20:31 -070065 private static final int UPDATE_TRANSFORM_MATRIX = 1;
Doris Liu6827ce22013-03-12 19:24:28 -070066 // module fields
67 private CameraActivity mActivity;
68 private View mRootView;
Likai Ding40d36372014-11-20 08:00:28 +080069 private TextureView mTextureView;
Doris Liu6827ce22013-03-12 19:24:28 -070070 // An review image having same size as preview. It is displayed when
71 // recording is stopped in capture intent.
72 private ImageView mReviewImage;
73 private View mReviewCancelButton;
74 private View mReviewDoneButton;
75 private View mReviewPlayButton;
76 private ShutterButton mShutterButton;
Manikanta Kanamarlapudiae019672014-01-06 14:31:43 +053077 private PauseButton mPauseButton;
Angus Konged15d1a2013-08-19 15:06:12 -070078 private ModuleSwitcher mSwitcher;
Doris Liu6827ce22013-03-12 19:24:28 -070079 private TextView mRecordingTimeView;
80 private LinearLayout mLabelsLinearLayout;
81 private View mTimeLapseLabel;
82 private RenderOverlay mRenderOverlay;
83 private PieRenderer mPieRenderer;
84 private VideoMenu mVideoMenu;
Doris Liu6432cd62013-06-13 17:20:31 -070085 private CameraControls mCameraControls;
Doris Liuc3679c02013-08-08 18:08:43 -070086 private SettingsPopup mPopup;
Doris Liu6827ce22013-03-12 19:24:28 -070087 private ZoomRenderer mZoomRenderer;
88 private PreviewGestures mGestures;
Doris Liu6432cd62013-06-13 17:20:31 -070089 private View mMenuButton;
Sascha Haeberling140c2632013-04-23 09:58:51 -070090 private OnScreenIndicators mOnScreenIndicators;
Doris Liu6827ce22013-03-12 19:24:28 -070091 private RotateLayout mRecordingTimeRect;
Doris Liufe6596c2013-10-08 11:03:37 -070092 private boolean mRecordingStarted = false;
Likai Ding40d36372014-11-20 08:00:28 +080093 private SurfaceTexture mSurfaceTexture;
Doris Liu6827ce22013-03-12 19:24:28 -070094 private VideoController mController;
95 private int mZoomMax;
96 private List<Integer> mZoomRatios;
Likai Ding512a1ad2014-11-20 08:00:10 +080097 private View mPreviewThumb;
Sascha Haeberling37f36112013-08-06 14:31:52 -070098 private View mFlashOverlay;
Santhosh Kumar H E6bc53a12013-10-25 13:14:10 +053099 private boolean mOrientationResize;
100 private boolean mPrevOrientationResize;
Kerong Suiea667a62014-04-08 17:52:03 +0800101 private boolean mIsTimeLapse = false;
Doris Liu6827ce22013-03-12 19:24:28 -0700102
Doris Liu3a45c332013-10-15 19:10:28 -0700103 private View mPreviewCover;
Doris Liu6432cd62013-06-13 17:20:31 -0700104 private SurfaceView mSurfaceView = null;
105 private int mPreviewWidth = 0;
106 private int mPreviewHeight = 0;
Likai Ding40d36372014-11-20 08:00:28 +0800107 private float mSurfaceTextureUncroppedWidth;
108 private float mSurfaceTextureUncroppedHeight;
Doris Liu6432cd62013-06-13 17:20:31 -0700109 private float mAspectRatio = 4f / 3f;
Santhosh Kumar H E6bc53a12013-10-25 13:14:10 +0530110 private boolean mAspectRatioResize;
Doris Liu6432cd62013-06-13 17:20:31 -0700111 private Matrix mMatrix = null;
Sascha Haeberling37f36112013-08-06 14:31:52 -0700112 private final AnimationManager mAnimationManager;
Doris Liu6432cd62013-06-13 17:20:31 -0700113 private final Handler mHandler = new Handler() {
114 @Override
115 public void handleMessage(Message msg) {
116 switch (msg.what) {
117 case UPDATE_TRANSFORM_MATRIX:
118 setTransformMatrix(mPreviewWidth, mPreviewHeight);
119 break;
120 default:
121 break;
122 }
123 }
124 };
125 private OnLayoutChangeListener mLayoutListener = new OnLayoutChangeListener() {
126 @Override
127 public void onLayoutChange(View v, int left, int top, int right,
128 int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
129 int width = right - left;
130 int height = bottom - top;
Likai Ding40d36372014-11-20 08:00:28 +0800131 // Full-screen screennail
132 int w = width;
133 int h = height;
134 if (CameraUtil.getDisplayRotation(mActivity) % 180 != 0) {
135 w = height;
136 h = width;
Doris Liu6432cd62013-06-13 17:20:31 -0700137 }
Santhosh Kumar H E6bc53a12013-10-25 13:14:10 +0530138 if (mPreviewWidth != width || mPreviewHeight != height
139 || (mOrientationResize != mPrevOrientationResize)
Likai Ding40d36372014-11-20 08:00:28 +0800140 || (mAspectRatioResize)) {
Doris Liu6432cd62013-06-13 17:20:31 -0700141 mPreviewWidth = width;
142 mPreviewHeight = height;
Likai Ding40d36372014-11-20 08:00:28 +0800143 onScreenSizeChanged(width, height, w, h);
Santhosh Kumar H E6bc53a12013-10-25 13:14:10 +0530144 mAspectRatioResize = false;
Doris Liu6432cd62013-06-13 17:20:31 -0700145 }
146 }
147 };
148
Doris Liu3a45c332013-10-15 19:10:28 -0700149 public void showPreviewCover() {
150 mPreviewCover.setVisibility(View.VISIBLE);
151 }
152
Doris Liuc3679c02013-08-08 18:08:43 -0700153 private class SettingsPopup extends PopupWindow {
154 public SettingsPopup(View popup) {
155 super(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
156 setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
157 setOutsideTouchable(true);
158 setFocusable(true);
159 popup.setVisibility(View.VISIBLE);
160 setContentView(popup);
161 showAtLocation(mRootView, Gravity.CENTER, 0, 0);
162 }
163
164 public void dismiss(boolean topLevelOnly) {
165 super.dismiss();
166 popupDismissed();
167 showUI();
Likai Ding546ba362014-11-21 01:52:54 +0800168 mVideoMenu.popupDismissed(topLevelOnly);
Sascha Haeberling4ec139d2013-10-09 23:46:20 -0700169
170 // Switch back into fullscreen/lights-out mode after popup
171 // is dimissed.
172 mActivity.setSystemBarsVisibility(false);
Doris Liuc3679c02013-08-08 18:08:43 -0700173 }
174
175 @Override
176 public void dismiss() {
177 // Called by Framework when touch outside the popup or hit back key
178 dismiss(true);
179 }
180 }
181
Doris Liu6827ce22013-03-12 19:24:28 -0700182 public VideoUI(CameraActivity activity, VideoController controller, View parent) {
183 mActivity = activity;
184 mController = controller;
185 mRootView = parent;
Likai Ding40d36372014-11-20 08:00:28 +0800186 mActivity.getLayoutInflater().inflate(R.layout.video_module, (ViewGroup) mRootView, true);
Doris Liu3a45c332013-10-15 19:10:28 -0700187 mPreviewCover = mRootView.findViewById(R.id.preview_cover);
Likai Ding40d36372014-11-20 08:00:28 +0800188 mTextureView = (TextureView) mRootView.findViewById(R.id.preview_content);
189 mTextureView.setSurfaceTextureListener(this);
190 mTextureView.addOnLayoutChangeListener(mLayoutListener);
Sascha Haeberling37f36112013-08-06 14:31:52 -0700191 mFlashOverlay = mRootView.findViewById(R.id.flash_overlay);
Doris Liu6432cd62013-06-13 17:20:31 -0700192 mShutterButton = (ShutterButton) mRootView.findViewById(R.id.shutter_button);
Angus Konged15d1a2013-08-19 15:06:12 -0700193 mSwitcher = (ModuleSwitcher) mRootView.findViewById(R.id.camera_switcher);
194 mSwitcher.setCurrentIndex(ModuleSwitcher.VIDEO_MODULE_INDEX);
195 mSwitcher.setSwitchListener(mActivity);
Doris Liu6827ce22013-03-12 19:24:28 -0700196 initializeMiscControls();
197 initializeControlByIntent();
198 initializeOverlay();
Manikanta Kanamarlapudiae019672014-01-06 14:31:43 +0530199 initializePauseButton();
Sascha Haeberling37f36112013-08-06 14:31:52 -0700200 mAnimationManager = new AnimationManager();
Santhosh Kumar H E6bc53a12013-10-25 13:14:10 +0530201 mOrientationResize = false;
202 mPrevOrientationResize = false;
Doris Liu6827ce22013-03-12 19:24:28 -0700203 }
204
Santhosh Kumar H E6bc53a12013-10-25 13:14:10 +0530205 public void cameraOrientationPreviewResize(boolean orientation){
206 mPrevOrientationResize = mOrientationResize;
207 mOrientationResize = orientation;
208 }
Doris Liu6432cd62013-06-13 17:20:31 -0700209
210 public void initializeSurfaceView() {
Likai Ding40d36372014-11-20 08:00:28 +0800211 mSurfaceView = new SurfaceView(mActivity);
212 ((ViewGroup) mRootView).addView(mSurfaceView, 0);
213 mSurfaceView.getHolder().addCallback(this);
Doris Liu6432cd62013-06-13 17:20:31 -0700214 }
215
Doris Liu6827ce22013-03-12 19:24:28 -0700216 private void initializeControlByIntent() {
Doris Liu2a7f44c2013-08-12 15:18:53 -0700217 mMenuButton = mRootView.findViewById(R.id.menu);
Doris Liu6432cd62013-06-13 17:20:31 -0700218 mMenuButton.setOnClickListener(new OnClickListener() {
Doris Liu6827ce22013-03-12 19:24:28 -0700219 @Override
220 public void onClick(View v) {
Likai Ding1e4d9572014-11-20 08:01:08 +0800221 if (mPieRenderer != null) {
222 mPieRenderer.showInCenter();
223 }
Doris Liu6827ce22013-03-12 19:24:28 -0700224 }
225 });
Doris Liu6432cd62013-06-13 17:20:31 -0700226
Doris Liu2a7f44c2013-08-12 15:18:53 -0700227 mCameraControls = (CameraControls) mRootView.findViewById(R.id.camera_controls);
Michael Kolbeb8adc12013-04-26 11:09:29 -0700228 mOnScreenIndicators = new OnScreenIndicators(mActivity,
Doris Liu2a7f44c2013-08-12 15:18:53 -0700229 mRootView.findViewById(R.id.on_screen_indicators));
Sascha Haeberling140c2632013-04-23 09:58:51 -0700230 mOnScreenIndicators.resetToDefault();
Doris Liu6827ce22013-03-12 19:24:28 -0700231 if (mController.isVideoCaptureIntent()) {
Doris Liu6432cd62013-06-13 17:20:31 -0700232 hideSwitcher();
233 mActivity.getLayoutInflater().inflate(R.layout.review_module_control,
234 (ViewGroup) mCameraControls);
Doris Liu6827ce22013-03-12 19:24:28 -0700235 // Cannot use RotateImageView for "done" and "cancel" button because
236 // the tablet layout uses RotateLayout, which cannot be cast to
237 // RotateImageView.
Doris Liu2a7f44c2013-08-12 15:18:53 -0700238 mReviewDoneButton = mRootView.findViewById(R.id.btn_done);
239 mReviewCancelButton = mRootView.findViewById(R.id.btn_cancel);
240 mReviewPlayButton = mRootView.findViewById(R.id.btn_play);
Doris Liu6827ce22013-03-12 19:24:28 -0700241 mReviewCancelButton.setVisibility(View.VISIBLE);
242 mReviewDoneButton.setOnClickListener(new OnClickListener() {
243 @Override
244 public void onClick(View v) {
245 mController.onReviewDoneClicked(v);
246 }
247 });
248 mReviewCancelButton.setOnClickListener(new OnClickListener() {
249 @Override
250 public void onClick(View v) {
251 mController.onReviewCancelClicked(v);
252 }
253 });
254 mReviewPlayButton.setOnClickListener(new OnClickListener() {
255 @Override
256 public void onClick(View v) {
257 mController.onReviewPlayClicked(v);
258 }
259 });
260 }
261 }
262
Doris Liu6432cd62013-06-13 17:20:31 -0700263 public void setPreviewSize(int width, int height) {
264 if (width == 0 || height == 0) {
265 Log.w(TAG, "Preview size should not be 0.");
266 return;
267 }
Santhosh Kumar H E6bc53a12013-10-25 13:14:10 +0530268 float ratio;
Doris Liu6432cd62013-06-13 17:20:31 -0700269 if (width > height) {
Santhosh Kumar H E6bc53a12013-10-25 13:14:10 +0530270 ratio = (float) width / height;
Doris Liu6432cd62013-06-13 17:20:31 -0700271 } else {
Santhosh Kumar H E6bc53a12013-10-25 13:14:10 +0530272 ratio = (float) height / width;
273 }
274 if (mOrientationResize &&
275 mActivity.getResources().getConfiguration().orientation
276 != Configuration.ORIENTATION_PORTRAIT) {
277 ratio = 1 / ratio;
278 }
279
280 if (ratio != mAspectRatio){
281 mAspectRatioResize = true;
282 mAspectRatio = ratio;
Doris Liu6432cd62013-06-13 17:20:31 -0700283 }
Likai Ding40d36372014-11-20 08:00:28 +0800284 mHandler.sendEmptyMessage(UPDATE_TRANSFORM_MATRIX);
Doris Liu6432cd62013-06-13 17:20:31 -0700285 }
286
287 public int getPreviewWidth() {
288 return mPreviewWidth;
289 }
290
291 public int getPreviewHeight() {
292 return mPreviewHeight;
293 }
294
Likai Ding40d36372014-11-20 08:00:28 +0800295 public void onScreenSizeChanged(int width, int height, int previewWidth, int previewHeight) {
296 setTransformMatrix(width, height);
297 }
Byunghun Jeon6ee7e412014-08-29 17:56:11 -0700298
Likai Ding40d36372014-11-20 08:00:28 +0800299 private void setTransformMatrix(int width, int height) {
300 mMatrix = mTextureView.getTransform(mMatrix);
301 int orientation = CameraUtil.getDisplayRotation(mActivity);
302 float scaleX = 1f, scaleY = 1f;
Doris Liu6432cd62013-06-13 17:20:31 -0700303 float scaledTextureWidth, scaledTextureHeight;
Likai Ding40d36372014-11-20 08:00:28 +0800304 if (mOrientationResize){
305 if (width/mAspectRatio > height){
Byunghun Jeon6ee7e412014-08-29 17:56:11 -0700306 scaledTextureHeight = height;
Likai Ding40d36372014-11-20 08:00:28 +0800307 scaledTextureWidth = (int)(height * mAspectRatio + 0.5f);
308 } else {
309 scaledTextureWidth = width;
310 scaledTextureHeight = (int)(width / mAspectRatio + 0.5f);
Santhosh Kumar H E6bc53a12013-10-25 13:14:10 +0530311 }
Doris Liu6432cd62013-06-13 17:20:31 -0700312 } else {
Santhosh Kumar H E6bc53a12013-10-25 13:14:10 +0530313 if (width > height) {
Likai Ding2f163f22014-09-04 17:43:28 +0800314 scaledTextureWidth = Math.max(width, height * mAspectRatio);
315 scaledTextureHeight = Math.max(height, width / mAspectRatio);
Santhosh Kumar H E6bc53a12013-10-25 13:14:10 +0530316 } else {
Likai Ding2f163f22014-09-04 17:43:28 +0800317 scaledTextureWidth = Math.max(width, height / mAspectRatio);
318 scaledTextureHeight = Math.max(height, width * mAspectRatio);
Santhosh Kumar H E6bc53a12013-10-25 13:14:10 +0530319 }
Doris Liu6432cd62013-06-13 17:20:31 -0700320 }
321
Likai Ding40d36372014-11-20 08:00:28 +0800322 if (mSurfaceTextureUncroppedWidth != scaledTextureWidth ||
323 mSurfaceTextureUncroppedHeight != scaledTextureHeight) {
324 mSurfaceTextureUncroppedWidth = scaledTextureWidth;
325 mSurfaceTextureUncroppedHeight = scaledTextureHeight;
326 }
327 scaleX = scaledTextureWidth / width;
328 scaleY = scaledTextureHeight / height;
329 mMatrix.setScale(scaleX, scaleY, (float) width / 2, (float) height / 2);
330 mTextureView.setTransform(mMatrix);
331
332 if (mSurfaceView != null && mSurfaceView.getVisibility() == View.VISIBLE) {
333 LayoutParams lp = (LayoutParams) mSurfaceView.getLayoutParams();
334 lp.width = (int) mSurfaceTextureUncroppedWidth;
335 lp.height = (int) mSurfaceTextureUncroppedHeight;
336 lp.gravity = Gravity.CENTER;
337 mSurfaceView.requestLayout();
338 }
Doris Liu6432cd62013-06-13 17:20:31 -0700339 }
340
Sascha Haeberling37f36112013-08-06 14:31:52 -0700341 /**
342 * Starts a flash animation
343 */
344 public void animateFlash() {
345 mAnimationManager.startFlashAnimation(mFlashOverlay);
346 }
347
348 /**
349 * Starts a capture animation
Doris Liu3973deb2013-08-21 13:42:22 -0700350 */
351 public void animateCapture() {
352 Bitmap bitmap = null;
Likai Ding40d36372014-11-20 08:00:28 +0800353 if (mTextureView != null) {
354 bitmap = mTextureView.getBitmap((int) mSurfaceTextureUncroppedWidth / 2,
355 (int) mSurfaceTextureUncroppedHeight / 2);
356 }
Doris Liu3973deb2013-08-21 13:42:22 -0700357 animateCapture(bitmap);
358 }
359
360 /**
361 * Starts a capture animation
Sascha Haeberling37f36112013-08-06 14:31:52 -0700362 * @param bitmap the captured image that we shrink and slide in the animation
363 */
364 public void animateCapture(Bitmap bitmap) {
Doris Liu3973deb2013-08-21 13:42:22 -0700365 if (bitmap == null) {
366 Log.e(TAG, "No valid bitmap for capture animation.");
367 return;
368 }
Likai Ding512a1ad2014-11-20 08:00:10 +0800369 ((ImageView) mPreviewThumb).setImageBitmap(bitmap);
Sascha Haeberling37f36112013-08-06 14:31:52 -0700370 mAnimationManager.startCaptureAnimation(mPreviewThumb);
371 }
372
373 /**
374 * Cancels on-going animations
375 */
376 public void cancelAnimations() {
377 mAnimationManager.cancelAnimations();
378 }
379
Doris Liu6432cd62013-06-13 17:20:31 -0700380 public void hideUI() {
Likai Ding1e4d9572014-11-20 08:01:08 +0800381 mCameraControls.setVisibility(View.INVISIBLE);
Doris Liu6432cd62013-06-13 17:20:31 -0700382 mSwitcher.closePopup();
383 }
384
385 public void showUI() {
Likai Ding1e4d9572014-11-20 08:01:08 +0800386 mCameraControls.setVisibility(View.VISIBLE);
Doris Liu6432cd62013-06-13 17:20:31 -0700387 }
388
Erin Dahlgren3044d8c2013-10-10 18:23:45 -0700389 public boolean arePreviewControlsVisible() {
Likai Ding1e4d9572014-11-20 08:01:08 +0800390 return (mCameraControls.getVisibility() == View.VISIBLE);
Erin Dahlgren3044d8c2013-10-10 18:23:45 -0700391 }
392
Doris Liu6432cd62013-06-13 17:20:31 -0700393 public void hideSwitcher() {
394 mSwitcher.closePopup();
395 mSwitcher.setVisibility(View.INVISIBLE);
396 }
397
398 public void showSwitcher() {
399 mSwitcher.setVisibility(View.VISIBLE);
400 }
401
Suman Mukherjeee33a01a2016-02-19 10:45:25 +0530402 public void setSwitcherIndex() {
403 mSwitcher.setCurrentIndex(ModuleSwitcher.VIDEO_MODULE_INDEX);
404 }
405
Doris Liu6827ce22013-03-12 19:24:28 -0700406 public boolean collapseCameraControls() {
407 boolean ret = false;
408 if (mPopup != null) {
409 dismissPopup(false);
410 ret = true;
411 }
412 return ret;
413 }
414
415 public boolean removeTopLevelPopup() {
416 if (mPopup != null) {
417 dismissPopup(true);
418 return true;
419 }
420 return false;
421 }
422
423 public void enableCameraControls(boolean enable) {
424 if (mGestures != null) {
425 mGestures.setZoomOnly(!enable);
426 }
427 if (mPieRenderer != null && mPieRenderer.showsItems()) {
428 mPieRenderer.hide();
429 }
430 }
431
Doris Liu59390062013-10-10 17:20:56 -0700432 public void initDisplayChangeListener() {
433 ((CameraRootView) mRootView).setDisplayChangeListener(this);
434 }
435
436 public void removeDisplayChangeListener() {
437 ((CameraRootView) mRootView).removeDisplayChangeListener();
438 }
439
Doris Liu6827ce22013-03-12 19:24:28 -0700440 public void overrideSettings(final String... keyvalues) {
Dimitar Borisov19656472014-09-24 17:32:06 +0300441 if (mVideoMenu != null) {
442 mVideoMenu.overrideSettings(keyvalues);
443 }
Doris Liu6827ce22013-03-12 19:24:28 -0700444 }
445
Doris Liu6827ce22013-03-12 19:24:28 -0700446 public void setOrientationIndicator(int orientation, boolean animation) {
Doris Liu6827ce22013-03-12 19:24:28 -0700447 // We change the orientation of the linearlayout only for phone UI
448 // because when in portrait the width is not enough.
449 if (mLabelsLinearLayout != null) {
450 if (((orientation / 90) & 1) == 0) {
451 mLabelsLinearLayout.setOrientation(LinearLayout.VERTICAL);
452 } else {
453 mLabelsLinearLayout.setOrientation(LinearLayout.HORIZONTAL);
454 }
455 }
456 mRecordingTimeRect.setOrientation(0, animation);
457 }
458
459 public SurfaceHolder getSurfaceHolder() {
Likai Ding40d36372014-11-20 08:00:28 +0800460 return mSurfaceView.getHolder();
Doris Liu6827ce22013-03-12 19:24:28 -0700461 }
462
463 public void hideSurfaceView() {
Doris Liu6432cd62013-06-13 17:20:31 -0700464 mSurfaceView.setVisibility(View.GONE);
Likai Ding40d36372014-11-20 08:00:28 +0800465 mTextureView.setVisibility(View.VISIBLE);
Doris Liu6432cd62013-06-13 17:20:31 -0700466 setTransformMatrix(mPreviewWidth, mPreviewHeight);
Doris Liu6827ce22013-03-12 19:24:28 -0700467 }
468
469 public void showSurfaceView() {
Doris Liu6432cd62013-06-13 17:20:31 -0700470 mSurfaceView.setVisibility(View.VISIBLE);
Likai Ding40d36372014-11-20 08:00:28 +0800471 mTextureView.setVisibility(View.GONE);
Doris Liu6432cd62013-06-13 17:20:31 -0700472 setTransformMatrix(mPreviewWidth, mPreviewHeight);
Doris Liu6827ce22013-03-12 19:24:28 -0700473 }
474
475 private void initializeOverlay() {
476 mRenderOverlay = (RenderOverlay) mRootView.findViewById(R.id.render_overlay);
477 if (mPieRenderer == null) {
478 mPieRenderer = new PieRenderer(mActivity);
Likai Ding546ba362014-11-21 01:52:54 +0800479 mVideoMenu = new VideoMenu(mActivity, this, mPieRenderer);
Doris Liu6827ce22013-03-12 19:24:28 -0700480 mPieRenderer.setPieListener(this);
481 }
482 mRenderOverlay.addRenderer(mPieRenderer);
483 if (mZoomRenderer == null) {
484 mZoomRenderer = new ZoomRenderer(mActivity);
485 }
486 mRenderOverlay.addRenderer(mZoomRenderer);
487 if (mGestures == null) {
Doris Liu6432cd62013-06-13 17:20:31 -0700488 mGestures = new PreviewGestures(mActivity, this, mZoomRenderer, mPieRenderer);
489 mRenderOverlay.setGestures(mGestures);
Doris Liu6827ce22013-03-12 19:24:28 -0700490 }
491 mGestures.setRenderOverlay(mRenderOverlay);
Sascha Haeberling4f91ab52013-05-21 11:26:13 -0700492
Likai Ding512a1ad2014-11-20 08:00:10 +0800493 mPreviewThumb = mRootView.findViewById(R.id.preview_thumb);
Sascha Haeberling4f91ab52013-05-21 11:26:13 -0700494 mPreviewThumb.setOnClickListener(new OnClickListener() {
495 @Override
496 public void onClick(View v) {
Doris Liufe6596c2013-10-08 11:03:37 -0700497 // Do not allow navigation to filmstrip during video recording
Likai Ding1e4d9572014-11-20 08:01:08 +0800498 if (!mRecordingStarted) {
Doris Liufe6596c2013-10-08 11:03:37 -0700499 mActivity.gotoGallery();
500 }
Sascha Haeberling4f91ab52013-05-21 11:26:13 -0700501 }
502 });
Doris Liu6827ce22013-03-12 19:24:28 -0700503 }
504
505 public void setPrefChangedListener(OnPreferenceChangedListener listener) {
506 mVideoMenu.setListener(listener);
507 }
508
509 private void initializeMiscControls() {
Doris Liu6827ce22013-03-12 19:24:28 -0700510 mReviewImage = (ImageView) mRootView.findViewById(R.id.review_image);
Doris Liu6827ce22013-03-12 19:24:28 -0700511 mShutterButton.setImageResource(R.drawable.btn_new_shutter_video);
512 mShutterButton.setOnShutterButtonListener(mController);
513 mShutterButton.setVisibility(View.VISIBLE);
514 mShutterButton.requestFocus();
515 mShutterButton.enableTouch(true);
516 mRecordingTimeView = (TextView) mRootView.findViewById(R.id.recording_time);
517 mRecordingTimeRect = (RotateLayout) mRootView.findViewById(R.id.recording_time_rect);
518 mTimeLapseLabel = mRootView.findViewById(R.id.time_lapse_label);
519 // The R.id.labels can only be found in phone layout.
520 // That is, mLabelsLinearLayout should be null in tablet layout.
521 mLabelsLinearLayout = (LinearLayout) mRootView.findViewById(R.id.labels);
522 }
523
Manikanta Kanamarlapudiae019672014-01-06 14:31:43 +0530524 private void initializePauseButton() {
525 mPauseButton = (PauseButton) mRootView.findViewById(R.id.video_pause);
526 mPauseButton.setOnPauseButtonListener(this);
527 }
528
Michael Kolb87880792013-04-30 15:38:49 -0700529 public void updateOnScreenIndicators(Parameters param, ComboPreferences prefs) {
Sascha Haeberling140c2632013-04-23 09:58:51 -0700530 mOnScreenIndicators.updateFlashOnScreenIndicator(param.getFlashMode());
Michael Kolb87880792013-04-30 15:38:49 -0700531 boolean location = RecordLocationPreference.get(
532 prefs, mActivity.getContentResolver());
533 mOnScreenIndicators.updateLocationIndicator(location);
534
Doris Liu6827ce22013-03-12 19:24:28 -0700535 }
536
537 public void setAspectRatio(double ratio) {
Santhosh Kumar H E6bc53a12013-10-25 13:14:10 +0530538 if (mOrientationResize &&
539 mActivity.getResources().getConfiguration().orientation
540 != Configuration.ORIENTATION_PORTRAIT) {
541 ratio = 1 / ratio;
542 }
543
Likai Ding40d36372014-11-20 08:00:28 +0800544 if (ratio != mAspectRatio){
Santhosh Kumar H E6bc53a12013-10-25 13:14:10 +0530545 mAspectRatioResize = true;
546 mAspectRatio = (float)ratio;
547 }
Likai Ding40d36372014-11-20 08:00:28 +0800548 mHandler.sendEmptyMessage(UPDATE_TRANSFORM_MATRIX);
Santhosh Kumar H E6bc53a12013-10-25 13:14:10 +0530549
Doris Liu6827ce22013-03-12 19:24:28 -0700550 }
551
552 public void showTimeLapseUI(boolean enable) {
553 if (mTimeLapseLabel != null) {
554 mTimeLapseLabel.setVisibility(enable ? View.VISIBLE : View.GONE);
555 }
Kerong Suiea667a62014-04-08 17:52:03 +0800556 mIsTimeLapse = enable;
Doris Liu6827ce22013-03-12 19:24:28 -0700557 }
558
Michael Kolb3bc96b22013-03-12 10:24:42 -0700559 private void openMenu() {
560 if (mPieRenderer != null) {
561 mPieRenderer.showInCenter();
562 }
563 }
564
Doris Liu6827ce22013-03-12 19:24:28 -0700565 public void dismissPopup(boolean topLevelOnly) {
Doris Liu69ef5ea2013-05-07 13:48:10 -0700566 // In review mode, we do not want to bring up the camera UI
567 if (mController.isInReviewMode()) return;
Doris Liu6827ce22013-03-12 19:24:28 -0700568 if (mPopup != null) {
Doris Liuc3679c02013-08-08 18:08:43 -0700569 mPopup.dismiss(topLevelOnly);
Doris Liu6827ce22013-03-12 19:24:28 -0700570 }
Doris Liuc3679c02013-08-08 18:08:43 -0700571 }
572
573 private void popupDismissed() {
574 mPopup = null;
575 }
576
577 public void showPopup(AbstractSettingPopup popup) {
578 hideUI();
579
580 if (mPopup != null) {
581 mPopup.dismiss(false);
582 }
583 mPopup = new SettingsPopup(popup);
Doris Liu6827ce22013-03-12 19:24:28 -0700584 }
585
586 public void onShowSwitcherPopup() {
587 hidePieRenderer();
588 }
589
590 public boolean hidePieRenderer() {
591 if (mPieRenderer != null && mPieRenderer.showsItems()) {
592 mPieRenderer.hide();
593 return true;
594 }
595 return false;
596 }
597
Doris Liu61f2b082013-03-27 17:25:43 -0700598 // disable preview gestures after shutter is pressed
599 public void setShutterPressed(boolean pressed) {
600 if (mGestures == null) return;
601 mGestures.setEnabled(!pressed);
602 }
603
Doris Liu6827ce22013-03-12 19:24:28 -0700604 public void enableShutter(boolean enable) {
605 if (mShutterButton != null) {
Shalaj Jain467b4f22014-11-10 14:01:09 -0800606 if (enable) {
607 Log.v(TAG, "Shutter Button enabled !!");
608 } else {
609 Log.v(TAG, "Shutter Button disabled !!");
610 }
Doris Liu6827ce22013-03-12 19:24:28 -0700611 mShutterButton.setEnabled(enable);
612 }
613 }
614
615 // PieListener
616 @Override
617 public void onPieOpened(int centerX, int centerY) {
Doris Liu6432cd62013-06-13 17:20:31 -0700618 setSwipingEnabled(false);
Andy Huibers249653e2013-11-11 22:30:49 -0800619 // Close module selection menu when pie menu is opened.
620 mSwitcher.closePopup();
Doris Liu6827ce22013-03-12 19:24:28 -0700621 }
622
623 @Override
624 public void onPieClosed() {
Doris Liu6432cd62013-06-13 17:20:31 -0700625 setSwipingEnabled(true);
626 }
627
628 public void setSwipingEnabled(boolean enable) {
629 mActivity.setSwipingEnabled(enable);
Doris Liu6827ce22013-03-12 19:24:28 -0700630 }
631
632 public void showPreviewBorder(boolean enable) {
Doris Liu6432cd62013-06-13 17:20:31 -0700633 // TODO: mPreviewFrameLayout.showBorder(enable);
Doris Liu6827ce22013-03-12 19:24:28 -0700634 }
635
636 // SingleTapListener
637 // Preview area is touched. Take a picture.
638 @Override
639 public void onSingleTapUp(View view, int x, int y) {
640 mController.onSingleTapUp(view, x, y);
641 }
642
Doris Liufe6596c2013-10-08 11:03:37 -0700643 public void showRecordingUI(boolean recording) {
644 mRecordingStarted = recording;
Doris Liu6432cd62013-06-13 17:20:31 -0700645 mMenuButton.setVisibility(recording ? View.GONE : View.VISIBLE);
Doris Liu6827ce22013-03-12 19:24:28 -0700646 mOnScreenIndicators.setVisibility(recording ? View.GONE : View.VISIBLE);
647 if (recording) {
Likai Ding1e4d9572014-11-20 08:01:08 +0800648 mShutterButton.setImageResource(R.drawable.btn_shutter_video_recording);
Doris Liu6432cd62013-06-13 17:20:31 -0700649 hideSwitcher();
Doris Liu6827ce22013-03-12 19:24:28 -0700650 mRecordingTimeView.setText("");
651 mRecordingTimeView.setVisibility(View.VISIBLE);
Kerong Suiea667a62014-04-08 17:52:03 +0800652 mPauseButton.setVisibility(mIsTimeLapse ? View.GONE : View.VISIBLE);
Doris Liu6827ce22013-03-12 19:24:28 -0700653 } else {
654 mShutterButton.setImageResource(R.drawable.btn_new_shutter_video);
Doris Liu2a7f44c2013-08-12 15:18:53 -0700655 if (!mController.isVideoCaptureIntent()) {
656 showSwitcher();
657 }
Doris Liu6827ce22013-03-12 19:24:28 -0700658 mRecordingTimeView.setVisibility(View.GONE);
Manikanta Kanamarlapudiae019672014-01-06 14:31:43 +0530659 mPauseButton.setVisibility(View.GONE);
Doris Liu6827ce22013-03-12 19:24:28 -0700660 }
661 }
662
663 public void showReviewImage(Bitmap bitmap) {
664 mReviewImage.setImageBitmap(bitmap);
665 mReviewImage.setVisibility(View.VISIBLE);
666 }
667
668 public void showReviewControls() {
Angus Kongb50b5cb2013-08-09 14:55:20 -0700669 CameraUtil.fadeOut(mShutterButton);
670 CameraUtil.fadeIn(mReviewDoneButton);
671 CameraUtil.fadeIn(mReviewPlayButton);
Doris Liu6827ce22013-03-12 19:24:28 -0700672 mReviewImage.setVisibility(View.VISIBLE);
Doris Liu6432cd62013-06-13 17:20:31 -0700673 mMenuButton.setVisibility(View.GONE);
Doris Liu6827ce22013-03-12 19:24:28 -0700674 mOnScreenIndicators.setVisibility(View.GONE);
675 }
676
677 public void hideReviewUI() {
678 mReviewImage.setVisibility(View.GONE);
679 mShutterButton.setEnabled(true);
Doris Liu6432cd62013-06-13 17:20:31 -0700680 mMenuButton.setVisibility(View.VISIBLE);
Doris Liu6827ce22013-03-12 19:24:28 -0700681 mOnScreenIndicators.setVisibility(View.VISIBLE);
Angus Kongb50b5cb2013-08-09 14:55:20 -0700682 CameraUtil.fadeOut(mReviewDoneButton);
683 CameraUtil.fadeOut(mReviewPlayButton);
684 CameraUtil.fadeIn(mShutterButton);
Doris Liu6827ce22013-03-12 19:24:28 -0700685 }
686
687 private void setShowMenu(boolean show) {
Kerong Sui8c238462014-04-08 15:49:29 +0800688 if (mController.isVideoCaptureIntent())
689 return;
Doris Liu6827ce22013-03-12 19:24:28 -0700690 if (mOnScreenIndicators != null) {
691 mOnScreenIndicators.setVisibility(show ? View.VISIBLE : View.GONE);
692 }
Likai Ding1e4d9572014-11-20 08:01:08 +0800693 if (mMenuButton != null) {
694 mMenuButton.setVisibility(show ? View.VISIBLE : View.GONE);
695 }
Doris Liu6827ce22013-03-12 19:24:28 -0700696 }
697
ztenghui7b265a62013-09-09 14:58:44 -0700698 public void onPreviewFocusChanged(boolean previewFocused) {
699 if (previewFocused) {
Doris Liu6432cd62013-06-13 17:20:31 -0700700 showUI();
701 } else {
702 hideUI();
703 }
Doris Liu6827ce22013-03-12 19:24:28 -0700704 if (mGestures != null) {
ztenghui7b265a62013-09-09 14:58:44 -0700705 mGestures.setEnabled(previewFocused);
Doris Liu6827ce22013-03-12 19:24:28 -0700706 }
Doris Liu6827ce22013-03-12 19:24:28 -0700707 if (mRenderOverlay != null) {
708 // this can not happen in capture mode
ztenghui7b265a62013-09-09 14:58:44 -0700709 mRenderOverlay.setVisibility(previewFocused ? View.VISIBLE : View.GONE);
Doris Liu6827ce22013-03-12 19:24:28 -0700710 }
ztenghui7b265a62013-09-09 14:58:44 -0700711 setShowMenu(previewFocused);
Doris Liu6827ce22013-03-12 19:24:28 -0700712 }
713
714 public void initializePopup(PreferenceGroup pref) {
715 mVideoMenu.initialize(pref);
716 }
717
718 public void initializeZoom(Parameters param) {
Doris Liu6432cd62013-06-13 17:20:31 -0700719 if (param == null || !param.isZoomSupported()) {
720 mGestures.setZoomEnabled(false);
721 return;
722 }
723 mGestures.setZoomEnabled(true);
Doris Liu6827ce22013-03-12 19:24:28 -0700724 mZoomMax = param.getMaxZoom();
725 mZoomRatios = param.getZoomRatios();
726 // Currently we use immediate zoom for fast zooming to get better UX and
727 // there is no plan to take advantage of the smooth zoom.
728 mZoomRenderer.setZoomMax(mZoomMax);
729 mZoomRenderer.setZoom(param.getZoom());
730 mZoomRenderer.setZoomValue(mZoomRatios.get(param.getZoom()));
731 mZoomRenderer.setOnZoomChangeListener(new ZoomChangeListener());
732 }
733
734 public void clickShutter() {
735 mShutterButton.performClick();
736 }
737
738 public void pressShutter(boolean pressed) {
739 mShutterButton.setPressed(pressed);
740 }
741
Doris Liu6432cd62013-06-13 17:20:31 -0700742 public View getShutterButton() {
743 return mShutterButton;
Doris Liu6827ce22013-03-12 19:24:28 -0700744 }
745
746 public void setRecordingTime(String text) {
747 mRecordingTimeView.setText(text);
748 }
749
750 public void setRecordingTimeTextColor(int color) {
751 mRecordingTimeView.setTextColor(color);
752 }
753
Doris Liu6432cd62013-06-13 17:20:31 -0700754 public boolean isVisible() {
ztenghui285a5be2013-10-09 15:59:47 -0700755 return mCameraControls.getVisibility() == View.VISIBLE;
Doris Liu6432cd62013-06-13 17:20:31 -0700756 }
757
ztenghui7b265a62013-09-09 14:58:44 -0700758 @Override
Doris Liu6432cd62013-06-13 17:20:31 -0700759 public void onDisplayChanged() {
760 mCameraControls.checkLayoutFlip();
761 mController.updateCameraOrientation();
762 }
763
Doris Liu6827ce22013-03-12 19:24:28 -0700764 private class ZoomChangeListener implements ZoomRenderer.OnZoomChangedListener {
765 @Override
766 public void onZoomValueChanged(int index) {
767 int newZoom = mController.onZoomChanged(index);
768 if (mZoomRenderer != null) {
769 mZoomRenderer.setZoomValue(mZoomRatios.get(newZoom));
770 }
771 }
772
773 @Override
774 public void onZoomStart() {
Alok Kediya23f3cf52013-10-02 17:42:36 +0530775 if (mPieRenderer != null) {
Santhosh Kumar H E78702742013-10-25 19:01:33 +0530776 if (!mRecordingStarted) mPieRenderer.hide();
Alok Kediya23f3cf52013-10-02 17:42:36 +0530777 mPieRenderer.setBlockFocus(true);
778 }
Doris Liu6827ce22013-03-12 19:24:28 -0700779 }
780
781 @Override
782 public void onZoomEnd() {
Alok Kediya23f3cf52013-10-02 17:42:36 +0530783 if (mPieRenderer != null) {
784 mPieRenderer.setBlockFocus(false);
785 }
Doris Liu6827ce22013-03-12 19:24:28 -0700786 }
787 }
Michael Kolb3bc96b22013-03-12 10:24:42 -0700788
Likai Ding40d36372014-11-20 08:00:28 +0800789 public SurfaceTexture getSurfaceTexture() {
790 return mSurfaceTexture;
791 }
792
793 // SurfaceTexture callbacks
Michael Kolb3bc96b22013-03-12 10:24:42 -0700794 @Override
Likai Ding40d36372014-11-20 08:00:28 +0800795 public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
796 mSurfaceTexture = surface;
797 mController.onPreviewUIReady();
798 }
799
800 @Override
801 public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
802 mSurfaceTexture = null;
803 mController.onPreviewUIDestroyed();
804 Log.d(TAG, "surfaceTexture is destroyed");
805 return true;
806 }
807
808 @Override
809 public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
810 }
811
812 @Override
813 public void onSurfaceTextureUpdated(SurfaceTexture surface) {
Andy Huibersfccf83b2013-11-06 14:37:26 -0800814 // Make sure preview cover is hidden if preview data is available.
815 if (mPreviewCover.getVisibility() != View.GONE) {
816 mPreviewCover.setVisibility(View.GONE);
817 }
Doris Liu6432cd62013-06-13 17:20:31 -0700818 }
819
Likai Ding40d36372014-11-20 08:00:28 +0800820 // SurfaceHolder callbacks
821 @Override
822 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
823 Log.v(TAG, "Surface changed. width=" + width + ". height=" + height);
824 }
825
Doris Liu6432cd62013-06-13 17:20:31 -0700826 @Override
827 public void surfaceCreated(SurfaceHolder holder) {
Likai Ding40d36372014-11-20 08:00:28 +0800828 Log.v(TAG, "Surface created");
Doris Liu6432cd62013-06-13 17:20:31 -0700829 }
830
831 @Override
832 public void surfaceDestroyed(SurfaceHolder holder) {
Likai Ding40d36372014-11-20 08:00:28 +0800833 Log.v(TAG, "Surface destroyed");
834 mController.stopPreview();
Sascha Haeberling4f91ab52013-05-21 11:26:13 -0700835 }
Manikanta Kanamarlapudiae019672014-01-06 14:31:43 +0530836
837 @Override
838 public void onButtonPause() {
839 mRecordingTimeView.setCompoundDrawablesWithIntrinsicBounds(
Likai Ding40d36372014-11-20 08:00:28 +0800840 R.drawable.ic_pausing_indicator, 0, 0, 0);
841 mController.onButtonPause();
Manikanta Kanamarlapudiae019672014-01-06 14:31:43 +0530842 }
843
844 @Override
845 public void onButtonContinue() {
846 mRecordingTimeView.setCompoundDrawablesWithIntrinsicBounds(
Likai Ding40d36372014-11-20 08:00:28 +0800847 R.drawable.ic_recording_indicator, 0, 0, 0);
Manikanta Kanamarlapudiae019672014-01-06 14:31:43 +0530848 mController.onButtonContinue();
849 }
850
851 public void resetPauseButton() {
852 mRecordingTimeView.setCompoundDrawablesWithIntrinsicBounds(
853 R.drawable.ic_recording_indicator, 0, 0, 0);
854 mPauseButton.setPaused(false);
855 }
kaiyizde529662014-07-21 16:47:27 +0800856
857 public void setPreference(String key, String value) {
858 mVideoMenu.setPreference(key, value);
859 }
Doris Liu6827ce22013-03-12 19:24:28 -0700860}