/* * 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.util.AttributeSet; import android.view.LayoutInflater; import android.view.Surface; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemSelectedListener; import android.widget.ArrayAdapter; import android.widget.Spinner; import android.widget.Button; import android.widget.ToggleButton; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; import java.util.List; import java.util.Locale; public class TargetControlPane extends ControlPane { // XML attributes /** Name of pane tag */ private static final String PANE_NAME = "target_pane"; /** Attribute: ID for pane (integer) */ private static final String PANE_ID = "id"; /** Attribute: Type of output (string), value must be one of OutputViewType.getXmlName() */ private static final String OUTPUT_TYPE = "type"; // End XML attributes /** * Available output view types * *

Adding new entries to this list requires updating createOutputView() as * well.

*/ private enum OutputViewType { SURFACE_VIEW, TEXTURE_VIEW, IMAGE_READER, RENDERSCRIPT, MEDIA_RECORDER, MEDIA_CODEC; static String getXmlName(OutputViewType type) { return type.toString().toLowerCase(Locale.US); } } private static int mTargetPaneIdCounter = 0; private int mPaneId; private List mCameraPanes; private Spinner mCameraSpinner; private ToggleButton mCameraConfigureToggle; private Button mPrepareButton; private Spinner mOutputSpinner; private TargetSubPane mCurrentOutput; private int mOrientation = 0; /** * Constructor for tooling only */ public TargetControlPane(Context context, AttributeSet attrs) { super(context, attrs, null, null); mPaneId = 0; setUpUI(context); } public TargetControlPane(TestingCamera21 tc, AttributeSet attrs, StatusListener listener) { super(tc, attrs, listener, tc.getPaneTracker()); mPaneId = mTargetPaneIdCounter++; setUpUI(tc); } public TargetControlPane(TestingCamera21 tc, XmlPullParser configParser, StatusListener listener) throws XmlPullParserException, IOException { super(tc, null, listener, tc.getPaneTracker()); configParser.require(XmlPullParser.START_TAG, XmlPullParser.NO_NAMESPACE, PANE_NAME); int paneId = getAttributeInt(configParser, PANE_ID, -1); if (paneId == -1) { mPaneId = mTargetPaneIdCounter++; } else { mPaneId = paneId; if (mPaneId >= mTargetPaneIdCounter) { mTargetPaneIdCounter = mPaneId + 1; } } configParser.next(); configParser.require(XmlPullParser.END_TAG, XmlPullParser.NO_NAMESPACE, PANE_NAME); setUpUI(tc); } /** * Get this target's Surface aimed at the given camera pane. If no target * for that camera is defined by this pane, returns null. * * @param paneName ID of the camera pane to return a Surface for * @return a Surface to configure for the camera device, or null if none * available */ public Surface getTargetSurfaceForCameraPane(String paneName) { if (paneName == null || mCurrentOutput == null) return null; boolean isMyTarget = paneName.equals(mCameraSpinner.getSelectedItem()) && mCameraConfigureToggle.isChecked(); mPrepareButton.setEnabled(isMyTarget); return isMyTarget ? mCurrentOutput.getOutputSurface() : null; } public void notifyPaneEvent(ControlPane sourcePane, PaneTracker.PaneEvent event) { switch (event) { case NEW_CAMERA_SELECTED: if (mCameraPanes.size() > 0 && sourcePane == mCameraPanes.get(mCameraSpinner.getSelectedItemPosition())) { if (mCurrentOutput != null) { mCurrentOutput.setTargetCameraPane((CameraControlPane) sourcePane); } } break; default: super.notifyPaneEvent(sourcePane, event); } } public void onOrientationChange(int orientation) { mOrientation = orientation; if (mCurrentOutput != null) { mCurrentOutput.setUiOrientation(mOrientation); } } private void setUpUI(Context context) { String paneTitle = String.format(Locale.US, "%s %d", context.getResources().getString(R.string.target_pane_title), mPaneId); this.setName(paneTitle); LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); inflater.inflate(R.layout.target_pane, this); mCameraSpinner = (Spinner) findViewById(R.id.target_pane_camera_spinner); mCameraSpinner.setOnItemSelectedListener(mCameraSpinnerListener); mCameraConfigureToggle = (ToggleButton) findViewById(R.id.target_pane_configure_toggle); mCameraConfigureToggle.setChecked(true); mPrepareButton = (Button) findViewById(R.id.target_pane_prepare_button); mPrepareButton.setEnabled(false); mPrepareButton.setOnClickListener(mPrepareButtonListener); mOutputSpinner = (Spinner) findViewById(R.id.target_pane_output_spinner); mOutputSpinner.setOnItemSelectedListener(mOutputSpinnerListener); OutputViewType[] outputTypes = OutputViewType.values(); String[] outputSpinnerItems = new String[outputTypes.length]; for (int i = 0; i < outputTypes.length; i++) { outputSpinnerItems[i] = outputTypes[i].toString(); } mOutputSpinner.setAdapter(new ArrayAdapter(getContext(), R.layout.spinner_item, outputSpinnerItems)); mPaneTracker.addPaneListener(new CameraPanesListener()); mCameraPanes = mPaneTracker.getPanes(CameraControlPane.class); updateCameraPaneList(); } private class CameraPanesListener extends PaneTracker.PaneSetChangedListener { 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 OnItemSelectedListener mCameraSpinnerListener = new OnItemSelectedListener() { @Override public void onItemSelected(AdapterView parent, View view, int pos, long id) { updateSubPaneCamera(); } @Override public void onNothingSelected(AdapterView arg0) { } }; private final OnClickListener mPrepareButtonListener = new OnClickListener() { @Override public void onClick(View v) { CameraControlPane currentCameraPane = mCameraPanes.get( mCameraSpinner.getSelectedItemPosition()); currentCameraPane.prepareSurface(mCurrentOutput.getOutputSurface()); } }; private OnItemSelectedListener mOutputSpinnerListener = new OnItemSelectedListener() { @Override public void onItemSelected(AdapterView parent, View view, int pos, long id) { mPrepareButton.setEnabled(false); if (mCurrentOutput != null) { TargetControlPane.this.removeView(mCurrentOutput); } OutputViewType outputType = OutputViewType.valueOf((String) mOutputSpinner.getSelectedItem()); mCurrentOutput = createOutputView(outputType); if (mCurrentOutput != null) { TargetControlPane.this.addView(mCurrentOutput); mCurrentOutput.setUiOrientation(mOrientation); updateSubPaneCamera(); } } @Override public void onNothingSelected(AdapterView arg0) { mPrepareButton.setEnabled(false); if (mCurrentOutput != null) { TargetControlPane.this.removeView(mCurrentOutput); mCurrentOutput = null; } } }; 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(getContext(), R.layout.spinner_item, cameraSpinnerItems)); mCameraSpinner.setSelection(newSelectionIndex); } private void updateSubPaneCamera() { if (mCameraPanes.size() > 0 && mCurrentOutput != null) { mCurrentOutput.setTargetCameraPane(mCameraPanes.get(mCameraSpinner .getSelectedItemPosition())); } } private TargetSubPane createOutputView(OutputViewType type) { TargetSubPane newPane = null; switch (type) { case IMAGE_READER: newPane = new ImageReaderSubPane(getContext(), null); break; case MEDIA_CODEC: case MEDIA_RECORDER: case RENDERSCRIPT: TLog.e("No implementation yet for view type %s", type); break; case SURFACE_VIEW: newPane = new SurfaceViewSubPane(getContext(), null); break; case TEXTURE_VIEW: newPane = new TextureViewSubPane(getContext(), null); break; } return newPane; } }