• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
getXmlName(OutputViewType type)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      */
TargetControlPane(Context context, AttributeSet attrs)88     public TargetControlPane(Context context, AttributeSet attrs) {
89         super(context, attrs, null, null);
90 
91         mPaneId = 0;
92         setUpUI(context);
93     }
94 
TargetControlPane(TestingCamera21 tc, AttributeSet attrs, StatusListener listener)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 
TargetControlPane(TestingCamera21 tc, XmlPullParser configParser, StatusListener listener)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      */
getTargetSurfaceForCameraPane(String paneName)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 
notifyPaneEvent(ControlPane sourcePane, PaneTracker.PaneEvent event)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 
onOrientationChange(int orientation)157     public void onOrientationChange(int orientation) {
158         mOrientation = orientation;
159         if (mCurrentOutput != null) {
160             mCurrentOutput.setUiOrientation(mOrientation);
161         }
162     }
163 
setUpUI(Context context)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> {
CameraPanesListener()200         public CameraPanesListener() {
201             super(CameraControlPane.class);
202         }
203 
204         @Override
onPaneAdded(ControlPane pane)205         public void onPaneAdded(ControlPane pane) {
206             mCameraPanes.add((CameraControlPane) pane);
207             updateCameraPaneList();
208         }
209 
210         @Override
onPaneRemoved(ControlPane pane)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 
updateCameraPaneList()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 
updateSubPaneCamera()269     private void updateSubPaneCamera() {
270         if (mCameraPanes.size() > 0 && mCurrentOutput != null) {
271             mCurrentOutput.setTargetCameraPane(mCameraPanes.get(mCameraSpinner
272                     .getSelectedItemPosition()));
273         }
274     }
275 
createOutputView(OutputViewType type)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