blob: 9d00969789d83325e49aaad83625f17f17da7b53 [file] [log] [blame]
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.camera;
import android.graphics.Bitmap;
import android.graphics.Point;
import android.graphics.SurfaceTexture;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.android.camera.app.OrientationManager;
import com.android.camera.debug.Log;
import com.android.camera.ui.PreviewOverlay;
import com.android.camera.ui.PreviewStatusListener;
import com.android.camera.ui.RotateLayout;
import com.android.camera.ui.focus.FocusRing;
import com.android.camera2.R;
import com.android.ex.camera2.portability.CameraCapabilities;
import com.android.ex.camera2.portability.CameraSettings;
public class VideoUI implements PreviewStatusListener {
private static final Log.Tag TAG = new Log.Tag("VideoUI");
private final static float UNSET = 0f;
private final PreviewOverlay mPreviewOverlay;
// module fields
private final CameraActivity mActivity;
private final View mRootView;
private final FocusRing mFocusRing;
// An review image having same size as preview. It is displayed when
// recording is stopped in capture intent.
private ImageView mReviewImage;
private TextView mRecordingTimeView;
private LinearLayout mLabelsLinearLayout;
private RotateLayout mRecordingTimeRect;
private boolean mRecordingStarted = false;
private final VideoController mController;
private float mZoomMax;
private float mAspectRatio = UNSET;
private final AnimationManager mAnimationManager;
@Override
public void onPreviewLayoutChanged(View v, int left, int top, int right,
int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
}
@Override
public boolean shouldAutoAdjustTransformMatrixOnLayout() {
return true;
}
@Override
public void onPreviewFlipped() {
mController.updateCameraOrientation();
}
private final GestureDetector.OnGestureListener mPreviewGestureListener
= new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onSingleTapUp(MotionEvent ev) {
mController.onSingleTapUp(null, (int) ev.getX(), (int) ev.getY());
return true;
}
};
public VideoUI(CameraActivity activity, VideoController controller, View parent) {
mActivity = activity;
mController = controller;
mRootView = parent;
ViewGroup moduleRoot = (ViewGroup) mRootView.findViewById(R.id.module_layout);
mActivity.getLayoutInflater().inflate(R.layout.video_module,
moduleRoot, true);
mPreviewOverlay = (PreviewOverlay) mRootView.findViewById(R.id.preview_overlay);
initializeMiscControls();
mAnimationManager = new AnimationManager();
mFocusRing = (FocusRing) mRootView.findViewById(R.id.focus_ring);
}
public void setPreviewSize(int width, int height) {
if (width == 0 || height == 0) {
Log.w(TAG, "Preview size should not be 0.");
return;
}
float aspectRatio;
if (width > height) {
aspectRatio = (float) width / height;
} else {
aspectRatio = (float) height / width;
}
setAspectRatio(aspectRatio);
}
public FocusRing getFocusRing() {
return mFocusRing;
}
/**
* Cancels on-going animations
*/
public void cancelAnimations() {
mAnimationManager.cancelAnimations();
}
public void setOrientationIndicator(int orientation, boolean animation) {
// We change the orientation of the linearlayout only for phone UI
// because when in portrait the width is not enough.
if (mLabelsLinearLayout != null) {
if (((orientation / 90) & 1) == 0) {
mLabelsLinearLayout.setOrientation(LinearLayout.VERTICAL);
} else {
mLabelsLinearLayout.setOrientation(LinearLayout.HORIZONTAL);
}
}
mRecordingTimeRect.setOrientation(0, animation);
}
private void initializeMiscControls() {
mReviewImage = (ImageView) mRootView.findViewById(R.id.review_image);
mRecordingTimeView = (TextView) mRootView.findViewById(R.id.recording_time);
mRecordingTimeRect = (RotateLayout) mRootView.findViewById(R.id.recording_time_rect);
// The R.id.labels can only be found in phone layout.
// That is, mLabelsLinearLayout should be null in tablet layout.
mLabelsLinearLayout = (LinearLayout) mRootView.findViewById(R.id.labels);
}
public void updateOnScreenIndicators(CameraSettings settings) {
}
public void setAspectRatio(float ratio) {
if (ratio <= 0) {
return;
}
float aspectRatio = ratio > 1 ? ratio : 1 / ratio;
if (aspectRatio != mAspectRatio) {
mAspectRatio = aspectRatio;
mController.updatePreviewAspectRatio(mAspectRatio);
}
}
public void setSwipingEnabled(boolean enable) {
mActivity.setSwipingEnabled(enable);
}
public void showPreviewBorder(boolean enable) {
// TODO: mPreviewFrameLayout.showBorder(enable);
}
public void showRecordingUI(boolean recording) {
mRecordingStarted = recording;
if (recording) {
mRecordingTimeView.setText("");
mRecordingTimeView.setVisibility(View.VISIBLE);
mRecordingTimeView.announceForAccessibility(
mActivity.getResources().getString(R.string.video_recording_started));
} else {
mRecordingTimeView.announceForAccessibility(
mActivity.getResources().getString(R.string.video_recording_stopped));
mRecordingTimeView.setVisibility(View.GONE);
}
}
public void showReviewImage(Bitmap bitmap) {
mReviewImage.setImageBitmap(bitmap);
mReviewImage.setVisibility(View.VISIBLE);
}
public void showReviewControls() {
mActivity.getCameraAppUI().transitionToIntentReviewLayout();
mReviewImage.setVisibility(View.VISIBLE);
}
public void initializeZoom(CameraSettings settings, CameraCapabilities capabilities) {
mZoomMax = capabilities.getMaxZoomRatio();
// Currently we use immediate zoom for fast zooming to get better UX and
// there is no plan to take advantage of the smooth zoom.
// TODO: setup zoom through App UI.
mPreviewOverlay.setupZoom(mZoomMax, settings.getCurrentZoomRatio(),
new ZoomChangeListener());
}
public void setRecordingTime(String text) {
mRecordingTimeView.setText(text);
}
public void setRecordingTimeTextColor(int color) {
mRecordingTimeView.setTextColor(color);
}
public boolean isVisible() {
return false;
}
@Override
public GestureDetector.OnGestureListener getGestureListener() {
return mPreviewGestureListener;
}
@Override
public View.OnTouchListener getTouchListener() {
return null;
}
/**
* Hide the focus indicator.
*/
public void hidePassiveFocusIndicator() {
if (mFocusRing != null) {
Log.v(TAG, "mFocusRing.stopFocusAnimations()");
mFocusRing.stopFocusAnimations();
}
}
/**
* Show the passive focus indicator.
*/
public void showPassiveFocusIndicator() {
if (mFocusRing != null) {
mFocusRing.startPassiveFocus();
}
}
/**
* @return The size of the available preview area.
*/
public Point getPreviewScreenSize() {
return new Point(mRootView.getMeasuredWidth(), mRootView.getMeasuredHeight());
}
/**
* Adjust UI to an orientation change if necessary.
*/
public void onOrientationChanged(OrientationManager orientationManager,
OrientationManager.DeviceOrientation deviceOrientation) {
// do nothing.
}
private class ZoomChangeListener implements PreviewOverlay.OnZoomChangedListener {
@Override
public void onZoomValueChanged(float ratio) {
mController.onZoomChanged(ratio);
}
@Override
public void onZoomStart() {
}
@Override
public void onZoomEnd() {
}
}
// SurfaceTexture callbacks
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
mController.onPreviewUIReady();
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
mController.onPreviewUIDestroyed();
Log.d(TAG, "surfaceTexture is destroyed");
return true;
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
public void onPause() {
// recalculate aspect ratio when restarting.
mAspectRatio = 0.0f;
}
}