• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
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 
17 package com.android.camera;
18 
19 import android.graphics.Bitmap;
20 import android.graphics.Point;
21 import android.graphics.SurfaceTexture;
22 import android.view.GestureDetector;
23 import android.view.MotionEvent;
24 import android.view.View;
25 import android.view.ViewGroup;
26 import android.widget.ImageView;
27 import android.widget.LinearLayout;
28 import android.widget.TextView;
29 
30 import com.android.camera.debug.Log;
31 import com.android.camera.ui.FocusOverlay;
32 import com.android.camera.ui.PreviewOverlay;
33 import com.android.camera.ui.PreviewStatusListener;
34 import com.android.camera.ui.RotateLayout;
35 import com.android.camera.widget.VideoRecordingHints;
36 import com.android.camera2.R;
37 import com.android.ex.camera2.portability.CameraCapabilities;
38 import com.android.ex.camera2.portability.CameraSettings;
39 
40 import java.util.List;
41 
42 public class VideoUI implements PreviewStatusListener {
43     private static final Log.Tag TAG = new Log.Tag("VideoUI");
44 
45     private final static float UNSET = 0f;
46     private final PreviewOverlay mPreviewOverlay;
47     // module fields
48     private final CameraActivity mActivity;
49     private final View mRootView;
50     private final FocusOverlay mFocusUI;
51     // An review image having same size as preview. It is displayed when
52     // recording is stopped in capture intent.
53     private ImageView mReviewImage;
54     private VideoRecordingHints mVideoHints;
55     private TextView mRecordingTimeView;
56     private LinearLayout mLabelsLinearLayout;
57     private RotateLayout mRecordingTimeRect;
58     private boolean mRecordingStarted = false;
59     private final VideoController mController;
60     private float mZoomMax;
61 
62     private float mAspectRatio = UNSET;
63     private final AnimationManager mAnimationManager;
64 
65     @Override
onPreviewLayoutChanged(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom)66     public void onPreviewLayoutChanged(View v, int left, int top, int right,
67             int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
68     }
69 
70     @Override
shouldAutoAdjustTransformMatrixOnLayout()71     public boolean shouldAutoAdjustTransformMatrixOnLayout() {
72         return true;
73     }
74 
75     @Override
shouldAutoAdjustBottomBar()76     public boolean shouldAutoAdjustBottomBar() {
77         return true;
78     }
79 
80     @Override
onPreviewFlipped()81     public void onPreviewFlipped() {
82         mController.updateCameraOrientation();
83     }
84 
85     private final GestureDetector.OnGestureListener mPreviewGestureListener
86             = new GestureDetector.SimpleOnGestureListener() {
87         @Override
88         public boolean onSingleTapUp(MotionEvent ev) {
89             if (mVideoHints.getVisibility() == View.VISIBLE) {
90                 mVideoHints.setVisibility(View.INVISIBLE);
91             } else {
92                 mController.onSingleTapUp(null, (int) ev.getX(), (int) ev.getY());
93             }
94             return true;
95         }
96     };
97 
VideoUI(CameraActivity activity, VideoController controller, View parent)98     public VideoUI(CameraActivity activity, VideoController controller, View parent) {
99         mActivity = activity;
100         mController = controller;
101         mRootView = parent;
102         ViewGroup moduleRoot = (ViewGroup) mRootView.findViewById(R.id.module_layout);
103         mActivity.getLayoutInflater().inflate(R.layout.video_module,
104                 moduleRoot, true);
105 
106         mPreviewOverlay = (PreviewOverlay) mRootView.findViewById(R.id.preview_overlay);
107 
108         initializeMiscControls();
109         mAnimationManager = new AnimationManager();
110         mFocusUI = (FocusOverlay) mRootView.findViewById(R.id.focus_overlay);
111         mVideoHints = (VideoRecordingHints) mRootView.findViewById(R.id.video_shooting_hints);
112     }
113 
setPreviewSize(int width, int height)114     public void setPreviewSize(int width, int height) {
115         if (width == 0 || height == 0) {
116             Log.w(TAG, "Preview size should not be 0.");
117             return;
118         }
119         float aspectRatio;
120         if (width > height) {
121             aspectRatio = (float) width / height;
122         } else {
123             aspectRatio = (float) height / width;
124         }
125         setAspectRatio(aspectRatio);
126     }
127 
getFocusUI()128     public FocusOverlayManager.FocusUI getFocusUI() {
129         return mFocusUI;
130     }
131 
132     /**
133      * Starts a flash animation
134      */
animateFlash()135     public void animateFlash() {
136         mController.startPreCaptureAnimation();
137     }
138 
139     /**
140      * Cancels on-going animations
141      */
cancelAnimations()142     public void cancelAnimations() {
143         mAnimationManager.cancelAnimations();
144     }
145 
setOrientationIndicator(int orientation, boolean animation)146     public void setOrientationIndicator(int orientation, boolean animation) {
147         // We change the orientation of the linearlayout only for phone UI
148         // because when in portrait the width is not enough.
149         if (mLabelsLinearLayout != null) {
150             if (((orientation / 90) & 1) == 0) {
151                 mLabelsLinearLayout.setOrientation(LinearLayout.VERTICAL);
152             } else {
153                 mLabelsLinearLayout.setOrientation(LinearLayout.HORIZONTAL);
154             }
155         }
156         mRecordingTimeRect.setOrientation(0, animation);
157     }
158 
initializeMiscControls()159     private void initializeMiscControls() {
160         mReviewImage = (ImageView) mRootView.findViewById(R.id.review_image);
161         mRecordingTimeView = (TextView) mRootView.findViewById(R.id.recording_time);
162         mRecordingTimeRect = (RotateLayout) mRootView.findViewById(R.id.recording_time_rect);
163         // The R.id.labels can only be found in phone layout.
164         // That is, mLabelsLinearLayout should be null in tablet layout.
165         mLabelsLinearLayout = (LinearLayout) mRootView.findViewById(R.id.labels);
166     }
167 
updateOnScreenIndicators(CameraSettings settings)168     public void updateOnScreenIndicators(CameraSettings settings) {
169     }
170 
setAspectRatio(float ratio)171     public void setAspectRatio(float ratio) {
172         if (ratio <= 0) {
173             return;
174         }
175         float aspectRatio = ratio > 1 ? ratio : 1 / ratio;
176         if (aspectRatio != mAspectRatio) {
177             mAspectRatio = aspectRatio;
178             mController.updatePreviewAspectRatio(mAspectRatio);
179         }
180     }
181 
setSwipingEnabled(boolean enable)182     public void setSwipingEnabled(boolean enable) {
183         mActivity.setSwipingEnabled(enable);
184     }
185 
showPreviewBorder(boolean enable)186     public void showPreviewBorder(boolean enable) {
187        // TODO: mPreviewFrameLayout.showBorder(enable);
188     }
189 
showRecordingUI(boolean recording)190     public void showRecordingUI(boolean recording) {
191         mRecordingStarted = recording;
192         if (recording) {
193             mRecordingTimeView.setText("");
194             mRecordingTimeView.setVisibility(View.VISIBLE);
195             mRecordingTimeView.announceForAccessibility(
196                     mActivity.getResources().getString(R.string.video_recording_started));
197         } else {
198             mRecordingTimeView.announceForAccessibility(
199                     mActivity.getResources().getString(R.string.video_recording_stopped));
200             mRecordingTimeView.setVisibility(View.GONE);
201         }
202     }
203 
showReviewImage(Bitmap bitmap)204     public void showReviewImage(Bitmap bitmap) {
205         mReviewImage.setImageBitmap(bitmap);
206         mReviewImage.setVisibility(View.VISIBLE);
207     }
208 
showReviewControls()209     public void showReviewControls() {
210         mActivity.getCameraAppUI().transitionToIntentReviewLayout();
211         mReviewImage.setVisibility(View.VISIBLE);
212     }
213 
initializeZoom(CameraSettings settings, CameraCapabilities capabilities)214     public void initializeZoom(CameraSettings settings, CameraCapabilities capabilities) {
215         mZoomMax = capabilities.getMaxZoomRatio();
216         // Currently we use immediate zoom for fast zooming to get better UX and
217         // there is no plan to take advantage of the smooth zoom.
218         // TODO: setup zoom through App UI.
219         mPreviewOverlay.setupZoom(mZoomMax, settings.getCurrentZoomRatio(),
220                 new ZoomChangeListener());
221     }
222 
setRecordingTime(String text)223     public void setRecordingTime(String text) {
224         mRecordingTimeView.setText(text);
225     }
226 
setRecordingTimeTextColor(int color)227     public void setRecordingTimeTextColor(int color) {
228         mRecordingTimeView.setTextColor(color);
229     }
230 
isVisible()231     public boolean isVisible() {
232         return false;
233     }
234 
235     @Override
getGestureListener()236     public GestureDetector.OnGestureListener getGestureListener() {
237         return mPreviewGestureListener;
238     }
239 
240     @Override
getTouchListener()241     public View.OnTouchListener getTouchListener() {
242         return null;
243     }
244 
245     /**
246      * Shows or hides focus UI.
247      *
248      * @param show shows focus UI when true, hides it otherwise
249      */
showFocusUI(boolean show)250     public void showFocusUI(boolean show) {
251         if (mFocusUI != null) {
252             mFocusUI.setVisibility(show ? View.VISIBLE : View.INVISIBLE);
253         }
254     }
255 
256     /**
257      * Shows or hides video recording hints.
258      *
259      * @param show shows video recording hints when true, hides it otherwise.
260      */
showVideoRecordingHints(boolean show)261     public void showVideoRecordingHints(boolean show) {
262         mVideoHints.setVisibility(show ? View.VISIBLE : View.INVISIBLE);
263     }
264 
265     /**
266      * @return The size of the available preview area.
267      */
getPreviewScreenSize()268     public Point getPreviewScreenSize() {
269         return new Point(mRootView.getMeasuredWidth(), mRootView.getMeasuredHeight());
270     }
271 
onOrientationChanged(int orientation)272     public void onOrientationChanged(int orientation) {
273         mVideoHints.onOrientationChanged(orientation);
274     }
275 
276     private class ZoomChangeListener implements PreviewOverlay.OnZoomChangedListener {
277         @Override
onZoomValueChanged(float ratio)278         public void onZoomValueChanged(float ratio) {
279             mController.onZoomChanged(ratio);
280         }
281 
282         @Override
onZoomStart()283         public void onZoomStart() {
284         }
285 
286         @Override
onZoomEnd()287         public void onZoomEnd() {
288         }
289     }
290 
291     // SurfaceTexture callbacks
292     @Override
onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height)293     public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
294         mController.onPreviewUIReady();
295     }
296 
297     @Override
onSurfaceTextureDestroyed(SurfaceTexture surface)298     public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
299         mController.onPreviewUIDestroyed();
300         Log.d(TAG, "surfaceTexture is destroyed");
301         return true;
302     }
303 
304     @Override
onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height)305     public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
306     }
307 
308     @Override
onSurfaceTextureUpdated(SurfaceTexture surface)309     public void onSurfaceTextureUpdated(SurfaceTexture surface) {
310     }
311 
onPause()312     public void onPause() {
313         // recalculate aspect ratio when restarting.
314         mAspectRatio = 0.0f;
315     }
316 }
317