/*
* 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;
}
}