| /* |
| * Copyright (C) 2014 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.testingcamera2; |
| |
| import android.content.Context; |
| import android.hardware.camera2.CameraDevice; |
| import android.hardware.camera2.CaptureRequest; |
| import android.util.AttributeSet; |
| import android.view.LayoutInflater; |
| import android.view.Surface; |
| import android.view.View; |
| import android.widget.ArrayAdapter; |
| import android.widget.Button; |
| import android.widget.ListView; |
| import android.widget.Spinner; |
| |
| import org.xmlpull.v1.XmlPullParser; |
| import org.xmlpull.v1.XmlPullParserException; |
| |
| import java.io.IOException; |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.Locale; |
| |
| public class RequestControlPane extends ControlPane { |
| // XML attributes |
| |
| /** Name of pane tag */ |
| private static final String PANE_NAME = "request_pane"; |
| |
| /** Attribute: ID for pane (integer) */ |
| private static final String PANE_ID = "id"; |
| |
| // End XML attributes |
| |
| private enum TemplateType { |
| MANUAL(CameraDevice.TEMPLATE_MANUAL), |
| PREVIEW(CameraDevice.TEMPLATE_PREVIEW), |
| RECORD(CameraDevice.TEMPLATE_RECORD), |
| STILL_CAPTURE(CameraDevice.TEMPLATE_STILL_CAPTURE), |
| VIDEO_SNAPSHOT(CameraDevice.TEMPLATE_VIDEO_SNAPSHOT), |
| ZERO_SHUTTER_LAG(CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG); |
| |
| private int mTemplateVal; |
| |
| TemplateType(int templateVal) { |
| mTemplateVal = templateVal; |
| } |
| |
| int getTemplateValue() { |
| return mTemplateVal; |
| } |
| } |
| |
| private static int mRequestPaneIdCounter = 0; |
| |
| private final int mPaneId; |
| |
| private List<CameraControlPane> mCameraPanes; |
| private final List<TargetControlPane> mTargetPanes = new ArrayList<TargetControlPane>(); |
| |
| private Spinner mCameraSpinner; |
| private Spinner mTemplateSpinner; |
| private ListView mOutputListView; |
| |
| private CheckableListAdapter mOutputAdapter; |
| |
| /** |
| * Constructor for tooling only |
| */ |
| public RequestControlPane(Context context, AttributeSet attrs) { |
| super(context, attrs, null, null); |
| |
| mPaneId = 0; |
| setUpUI(context); |
| } |
| |
| public RequestControlPane(TestingCamera21 tc, AttributeSet attrs, StatusListener listener) { |
| super(tc, attrs, listener, tc.getPaneTracker()); |
| |
| mPaneId = mRequestPaneIdCounter++; |
| setUpUI(tc); |
| } |
| |
| public RequestControlPane(TestingCamera21 tc, XmlPullParser configParser, |
| StatusListener listener) throws XmlPullParserException, IOException { |
| super(tc, null, listener, tc.getPaneTracker()); |
| |
| this.setName(tc.getResources().getString(R.string.request_pane_title)); |
| |
| configParser.require(XmlPullParser.START_TAG, XmlPullParser.NO_NAMESPACE, PANE_NAME); |
| |
| int paneId = getAttributeInt(configParser, PANE_ID, -1); |
| if (paneId == -1) { |
| mPaneId = mRequestPaneIdCounter++; |
| } else { |
| mPaneId = paneId; |
| if (mPaneId >= mRequestPaneIdCounter) { |
| mRequestPaneIdCounter = mPaneId + 1; |
| } |
| } |
| |
| configParser.next(); |
| configParser.require(XmlPullParser.END_TAG, XmlPullParser.NO_NAMESPACE, PANE_NAME); |
| |
| setUpUI(tc); |
| } |
| |
| public void notifyPaneEvent(ControlPane sourcePane, PaneTracker.PaneEvent event) { |
| switch (event) { |
| case NEW_CAMERA_SELECTED: |
| if (mCameraPanes.size() > 0 |
| && sourcePane == mCameraPanes.get(mCameraSpinner.getSelectedItemPosition())) { |
| updateOutputList(); |
| } |
| break; |
| case CAMERA_CONFIGURED: |
| if (mCameraPanes.size() > 0 |
| && sourcePane == mCameraPanes.get(mCameraSpinner.getSelectedItemPosition())) { |
| updateOutputList(); |
| } |
| break; |
| default: |
| super.notifyPaneEvent(sourcePane, event); |
| } |
| } |
| |
| private void setUpUI(Context context) { |
| String paneName = |
| String.format(Locale.US, "%s %d", |
| context.getResources().getString(R.string.request_pane_title), mPaneId); |
| this.setName(paneName); |
| |
| LayoutInflater inflater = |
| (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); |
| |
| inflater.inflate(R.layout.request_pane, this); |
| |
| Button captureButton = (Button) findViewById(R.id.request_pane_capture_button); |
| captureButton.setOnClickListener(mCaptureButtonListener); |
| Button repeatButton = (Button) findViewById(R.id.request_pane_repeat_button); |
| repeatButton.setOnClickListener(mRepeatButtonListener); |
| |
| mCameraSpinner = (Spinner) findViewById(R.id.request_pane_camera_spinner); |
| mTemplateSpinner = (Spinner) findViewById(R.id.request_pane_template_spinner); |
| mOutputListView = (ListView) findViewById(R.id.request_pane_output_listview); |
| |
| mOutputAdapter = new CheckableListAdapter(context, R.layout.checkable_list_item, |
| new ArrayList<CheckableListAdapter.CheckableItem>()); |
| mOutputListView.setAdapter(mOutputAdapter); |
| |
| String[] templateNames = new String[TemplateType.values().length]; |
| for (int i = 0; i < templateNames.length; i++) { |
| templateNames[i] = TemplateType.values()[i].toString(); |
| } |
| mTemplateSpinner.setAdapter(new ArrayAdapter<String>(getContext(), R.layout.spinner_item, |
| templateNames)); |
| |
| mPaneTracker.addPaneListener(new CameraPanesListener()); |
| mCameraPanes = mPaneTracker.getPanes(CameraControlPane.class); |
| updateCameraPaneList(); |
| } |
| |
| private class CameraPanesListener extends PaneTracker.PaneSetChangedListener<CameraControlPane> { |
| public CameraPanesListener() { |
| super(CameraControlPane.class); |
| } |
| |
| @Override |
| public void onPaneAdded(ControlPane pane) { |
| mCameraPanes.add((CameraControlPane) pane); |
| updateCameraPaneList(); |
| } |
| |
| @Override |
| public void onPaneRemoved(ControlPane pane) { |
| mCameraPanes.remove((CameraControlPane) pane); |
| updateCameraPaneList(); |
| } |
| } |
| |
| private OnClickListener mCaptureButtonListener = new OnClickListener() { |
| @Override |
| public void onClick(View v) { |
| if (mCameraPanes.size() == 0) { |
| TLog.e("No camera selected for request"); |
| return; |
| } |
| CameraControlPane camera = mCameraPanes.get(mCameraSpinner.getSelectedItemPosition()); |
| |
| CaptureRequest request = createRequest(camera); |
| if (request != null) { |
| camera.capture(request); |
| } |
| } |
| }; |
| |
| private OnClickListener mRepeatButtonListener = new OnClickListener() { |
| @Override |
| public void onClick(View v) { |
| if (mCameraPanes.size() == 0) { |
| TLog.e("No camera selected for request"); |
| return; |
| } |
| CameraControlPane camera = mCameraPanes.get(mCameraSpinner.getSelectedItemPosition()); |
| |
| CaptureRequest request = createRequest(camera); |
| if (request != null) { |
| camera.repeat(request); |
| } |
| } |
| }; |
| |
| private CaptureRequest createRequest(CameraControlPane camera) { |
| if (mTargetPanes.size() == 0) { |
| TLog.e("No target(s) selected for request"); |
| return null; |
| } |
| |
| |
| TemplateType template = TemplateType.valueOf((String) mTemplateSpinner.getSelectedItem()); |
| CaptureRequest.Builder builder = camera.getRequestBuilder(template.getTemplateValue()); |
| // TODO: Add setting overrides |
| |
| List<Integer> targetPostions = mOutputAdapter.getCheckedPositions(); |
| for (int i : targetPostions) { |
| TargetControlPane target = mTargetPanes.get(i); |
| Surface targetSurface = target.getTargetSurfaceForCameraPane(camera.getPaneName()); |
| if (targetSurface == null) { |
| TLog.e("Target not configured for camera"); |
| return null; |
| } |
| builder.addTarget(targetSurface); |
| } |
| |
| CaptureRequest request = builder.build(); |
| return request; |
| } |
| |
| private void updateCameraPaneList() { |
| String currentSelection = (String) mCameraSpinner.getSelectedItem(); |
| int newSelectionIndex = 0; |
| String[] cameraSpinnerItems = new String[mCameraPanes.size()]; |
| for (int i = 0; i < cameraSpinnerItems.length; i++) { |
| cameraSpinnerItems[i] = mCameraPanes.get(i).getPaneName(); |
| if (cameraSpinnerItems[i].equals(currentSelection)) { |
| newSelectionIndex = i; |
| } |
| } |
| mCameraSpinner.setAdapter(new ArrayAdapter<String>(getContext(), R.layout.spinner_item, |
| cameraSpinnerItems)); |
| mCameraSpinner.setSelection(newSelectionIndex); |
| |
| updateOutputList(); |
| } |
| |
| private void updateOutputList() { |
| if (mCameraPanes.size() > 0) { |
| CameraControlPane currentCamera = |
| mCameraPanes.get(mCameraSpinner.getSelectedItemPosition()); |
| mTargetPanes.clear(); |
| List<TargetControlPane> newPanes = currentCamera.getCurrentConfiguredTargets(); |
| if (newPanes != null) { |
| mTargetPanes.addAll(currentCamera.getCurrentConfiguredTargets()); |
| } |
| |
| String[] outputSpinnerItems = new String[mTargetPanes.size()]; |
| for (int i = 0; i < outputSpinnerItems.length; i++) { |
| outputSpinnerItems[i] = mTargetPanes.get(i).getPaneName(); |
| } |
| |
| mOutputAdapter.updateItems(outputSpinnerItems); |
| |
| } |
| } |
| |
| } |