Home | History | Annotate | Download | only in testingcamera2
      1 /*
      2  * Copyright (C) 2014 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.testingcamera2;
     18 
     19 import android.content.Context;
     20 import android.util.AttributeSet;
     21 import android.view.LayoutInflater;
     22 import android.view.Surface;
     23 import android.view.View;
     24 import android.widget.AdapterView;
     25 import android.widget.AdapterView.OnItemSelectedListener;
     26 import android.widget.ArrayAdapter;
     27 import android.widget.Spinner;
     28 import android.widget.ToggleButton;
     29 
     30 import org.xmlpull.v1.XmlPullParser;
     31 import org.xmlpull.v1.XmlPullParserException;
     32 
     33 import java.io.IOException;
     34 import java.util.List;
     35 import java.util.Locale;
     36 
     37 public class TargetControlPane extends ControlPane {
     38     // XML attributes
     39 
     40     /** Name of pane tag */
     41     private static final String PANE_NAME = "target_pane";
     42 
     43     /** Attribute: ID for pane (integer) */
     44     private static final String PANE_ID = "id";
     45 
     46     /** Attribute: Type of output (string), value must be one of OutputViewType.getXmlName() */
     47     private static final String OUTPUT_TYPE = "type";
     48 
     49     // End XML attributes
     50 
     51     /**
     52      * Available output view types
     53      *
     54      * <p>Adding new entries to this list requires updating createOutputView() as
     55      * well.</p>
     56      */
     57     private enum OutputViewType {
     58         SURFACE_VIEW,
     59         TEXTURE_VIEW,
     60         IMAGE_READER,
     61         RENDERSCRIPT,
     62         MEDIA_RECORDER,
     63         MEDIA_CODEC;
     64 
     65         static String getXmlName(OutputViewType type) {
     66             return type.toString().toLowerCase(Locale.US);
     67         }
     68     }
     69 
     70     private static int mTargetPaneIdCounter = 0;
     71 
     72     private int mPaneId;
     73 
     74     private List<CameraControlPane> mCameraPanes;
     75 
     76     private Spinner mCameraSpinner;
     77     private ToggleButton mCameraConfigureToggle;
     78 
     79     private Spinner mOutputSpinner;
     80 
     81     private TargetSubPane mCurrentOutput;
     82 
     83     private int mOrientation = 0;
     84 
     85     /**
     86      * Constructor for tooling only
     87      */
     88     public TargetControlPane(Context context, AttributeSet attrs) {
     89         super(context, attrs, null, null);
     90 
     91         mPaneId = 0;
     92         setUpUI(context);
     93     }
     94 
     95     public TargetControlPane(TestingCamera21 tc, AttributeSet attrs, StatusListener listener) {
     96         super(tc, attrs, listener, tc.getPaneTracker());
     97 
     98         mPaneId = mTargetPaneIdCounter++;
     99         setUpUI(tc);
    100 
    101     }
    102 
    103     public TargetControlPane(TestingCamera21 tc, XmlPullParser configParser, StatusListener listener)
    104             throws XmlPullParserException, IOException {
    105         super(tc, null, listener, tc.getPaneTracker());
    106 
    107         configParser.require(XmlPullParser.START_TAG, XmlPullParser.NO_NAMESPACE, PANE_NAME);
    108 
    109         int paneId = getAttributeInt(configParser, PANE_ID, -1);
    110         if (paneId == -1) {
    111             mPaneId = mTargetPaneIdCounter++;
    112         } else {
    113             mPaneId = paneId;
    114             if (mPaneId >= mTargetPaneIdCounter) {
    115                 mTargetPaneIdCounter = mPaneId + 1;
    116             }
    117         }
    118 
    119         configParser.next();
    120         configParser.require(XmlPullParser.END_TAG, XmlPullParser.NO_NAMESPACE, PANE_NAME);
    121 
    122         setUpUI(tc);
    123     }
    124 
    125     /**
    126      * Get this target's Surface aimed at the given camera pane. If no target
    127      * for that camera is defined by this pane, returns null.
    128      *
    129      * @param paneName ID of the camera pane to return a Surface for
    130      * @return a Surface to configure for the camera device, or null if none
    131      *         available
    132      */
    133     public Surface getTargetSurfaceForCameraPane(String paneName) {
    134         if (paneName == null || mCurrentOutput == null) return null;
    135 
    136         boolean isMyTarget =
    137                 paneName.equals(mCameraSpinner.getSelectedItem()) &&
    138                 mCameraConfigureToggle.isChecked();
    139         return isMyTarget ? mCurrentOutput.getOutputSurface() : null;
    140     }
    141 
    142     public void notifyPaneEvent(ControlPane sourcePane, PaneTracker.PaneEvent event) {
    143         switch (event) {
    144         case NEW_CAMERA_SELECTED:
    145             if (mCameraPanes.size() > 0
    146                     && sourcePane == mCameraPanes.get(mCameraSpinner.getSelectedItemPosition())) {
    147                 if (mCurrentOutput != null) {
    148                     mCurrentOutput.setTargetCameraPane((CameraControlPane) sourcePane);
    149                 }
    150             }
    151             break;
    152         default:
    153             super.notifyPaneEvent(sourcePane, event);
    154         }
    155     }
    156 
    157     public void onOrientationChange(int orientation) {
    158         mOrientation = orientation;
    159         if (mCurrentOutput != null) {
    160             mCurrentOutput.setUiOrientation(mOrientation);
    161         }
    162     }
    163 
    164     private void setUpUI(Context context) {
    165 
    166         String paneTitle =
    167                 String.format(Locale.US, "%s %d",
    168                         context.getResources().getString(R.string.target_pane_title), mPaneId);
    169         this.setName(paneTitle);
    170 
    171         LayoutInflater inflater =
    172                 (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    173 
    174         inflater.inflate(R.layout.target_pane, this);
    175 
    176         mCameraSpinner = (Spinner) findViewById(R.id.target_pane_camera_spinner);
    177         mCameraSpinner.setOnItemSelectedListener(mCameraSpinnerListener);
    178         mCameraConfigureToggle = (ToggleButton) findViewById(R.id.target_pane_configure_toggle);
    179         mCameraConfigureToggle.setChecked(true);
    180 
    181         mOutputSpinner = (Spinner) findViewById(R.id.target_pane_output_spinner);
    182         mOutputSpinner.setOnItemSelectedListener(mOutputSpinnerListener);
    183 
    184         OutputViewType[] outputTypes = OutputViewType.values();
    185         String[] outputSpinnerItems = new String[outputTypes.length];
    186 
    187         for (int i = 0; i < outputTypes.length; i++) {
    188             outputSpinnerItems[i] = outputTypes[i].toString();
    189         }
    190         mOutputSpinner.setAdapter(new ArrayAdapter<String>(getContext(), R.layout.spinner_item,
    191                 outputSpinnerItems));
    192 
    193         mPaneTracker.addPaneListener(new CameraPanesListener());
    194         mCameraPanes = mPaneTracker.getPanes(CameraControlPane.class);
    195         updateCameraPaneList();
    196 
    197     }
    198 
    199     private class CameraPanesListener extends PaneTracker.PaneSetChangedListener<CameraControlPane> {
    200         public CameraPanesListener() {
    201             super(CameraControlPane.class);
    202         }
    203 
    204         @Override
    205         public void onPaneAdded(ControlPane pane) {
    206             mCameraPanes.add((CameraControlPane) pane);
    207             updateCameraPaneList();
    208         }
    209 
    210         @Override
    211         public void onPaneRemoved(ControlPane pane) {
    212             mCameraPanes.remove((CameraControlPane) pane);
    213             updateCameraPaneList();
    214         }
    215     }
    216 
    217     private OnItemSelectedListener mCameraSpinnerListener = new OnItemSelectedListener() {
    218         @Override
    219         public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
    220             updateSubPaneCamera();
    221         }
    222 
    223         @Override
    224         public void onNothingSelected(AdapterView<?> arg0) {
    225 
    226         }
    227     };
    228 
    229     private OnItemSelectedListener mOutputSpinnerListener = new OnItemSelectedListener() {
    230         @Override
    231         public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
    232             if (mCurrentOutput != null) {
    233                 TargetControlPane.this.removeView(mCurrentOutput);
    234             }
    235             OutputViewType outputType =
    236                     OutputViewType.valueOf((String) mOutputSpinner.getSelectedItem());
    237             mCurrentOutput = createOutputView(outputType);
    238             if (mCurrentOutput != null) {
    239                 TargetControlPane.this.addView(mCurrentOutput);
    240                 mCurrentOutput.setUiOrientation(mOrientation);
    241                 updateSubPaneCamera();
    242             }
    243         }
    244 
    245         @Override
    246         public void onNothingSelected(AdapterView<?> arg0) {
    247             if (mCurrentOutput != null) {
    248                 TargetControlPane.this.removeView(mCurrentOutput);
    249                 mCurrentOutput = null;
    250             }
    251         }
    252     };
    253 
    254     private void updateCameraPaneList() {
    255         String currentSelection = (String) mCameraSpinner.getSelectedItem();
    256         int newSelectionIndex = 0;
    257         String[] cameraSpinnerItems = new String[mCameraPanes.size()];
    258         for (int i = 0; i < cameraSpinnerItems.length; i++) {
    259             cameraSpinnerItems[i] = mCameraPanes.get(i).getPaneName();
    260             if (cameraSpinnerItems[i].equals(currentSelection)) {
    261                 newSelectionIndex = i;
    262             }
    263         }
    264         mCameraSpinner.setAdapter(new ArrayAdapter<String>(getContext(), R.layout.spinner_item,
    265                 cameraSpinnerItems));
    266         mCameraSpinner.setSelection(newSelectionIndex);
    267     }
    268 
    269     private void updateSubPaneCamera() {
    270         if (mCameraPanes.size() > 0 && mCurrentOutput != null) {
    271             mCurrentOutput.setTargetCameraPane(mCameraPanes.get(mCameraSpinner
    272                     .getSelectedItemPosition()));
    273         }
    274     }
    275 
    276     private TargetSubPane createOutputView(OutputViewType type) {
    277         TargetSubPane newPane = null;
    278         switch (type) {
    279             case IMAGE_READER:
    280                 newPane = new ImageReaderSubPane(getContext(), null);
    281                 break;
    282             case MEDIA_CODEC:
    283             case MEDIA_RECORDER:
    284             case RENDERSCRIPT:
    285                 TLog.e("No implementation yet for view type %s", type);
    286                 break;
    287             case SURFACE_VIEW:
    288                 newPane = new SurfaceViewSubPane(getContext(), null);
    289                 break;
    290             case TEXTURE_VIEW:
    291                 newPane = new TextureViewSubPane(getContext(), null);
    292                 break;
    293         }
    294         return newPane;
    295     }
    296 }
    297