OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / packages / apps / Mms / src / com / android / mms / ui / SlideshowActivity.java
1 /*
2  * Copyright (C) 2008 Esmertec AG.
3  * Copyright (C) 2008 The Android Open Source Project
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 package com.android.mms.ui;
19
20 import com.android.mms.R;
21 import com.android.mms.dom.AttrImpl;
22 import com.android.mms.dom.smil.SmilDocumentImpl;
23 import com.android.mms.dom.smil.SmilPlayer;
24 import com.android.mms.dom.smil.parser.SmilXmlSerializer;
25 import com.android.mms.model.LayoutModel;
26 import com.android.mms.model.RegionModel;
27 import com.android.mms.model.SlideshowModel;
28 import com.android.mms.model.SmilHelper;
29 import com.google.android.mms.MmsException;
30
31 import org.w3c.dom.NamedNodeMap;
32 import org.w3c.dom.Node;
33 import org.w3c.dom.NodeList;
34 import org.w3c.dom.events.Event;
35 import org.w3c.dom.events.EventListener;
36 import org.w3c.dom.events.EventTarget;
37 import org.w3c.dom.smil.SMILDocument;
38 import org.w3c.dom.smil.SMILElement;
39
40 import android.app.Activity;
41 import android.content.Intent;
42 import android.graphics.PixelFormat;
43 import android.net.Uri;
44 import android.os.Bundle;
45 import android.os.Handler;
46 import android.util.Config;
47 import android.util.Log;
48 import android.view.KeyEvent;
49 import android.view.MotionEvent;
50 import android.view.View;
51 import android.view.Window;
52 import android.view.View.OnClickListener;
53 import android.widget.MediaController;
54 import android.widget.MediaController.MediaPlayerControl;
55
56 import java.io.ByteArrayOutputStream;
57
58 /**
59  * Plays the given slideshow in full-screen mode with a common controller.
60  */
61 public class SlideshowActivity extends Activity implements EventListener {
62     private static final String TAG = "SlideshowActivity";
63     private static final boolean DEBUG = false;
64     private static final boolean LOCAL_LOGV = DEBUG ? Config.LOGD : Config.LOGV;
65
66     private MediaController mMediaController;
67     private SmilPlayer mSmilPlayer;
68
69     private Handler mHandler;
70
71     private SMILDocument mSmilDoc;
72
73     private SlideView mSlideView;
74
75     /**
76      * @return whether the Smil has MMS conformance layout.
77      * Refer to MMS Conformance Document OMA-MMS-CONF-v1_2-20050301-A
78      */
79     private static final boolean isMMSConformance(SMILDocument smilDoc) {
80         SMILElement head = smilDoc.getHead();
81         if (head == null) {
82             // No 'head' element
83             return false;
84         }
85         NodeList children = head.getChildNodes();
86         if (children == null || children.getLength() != 1) {
87             // The 'head' element should have only one child.
88             return false;
89         }
90         Node layout = children.item(0);
91         if (layout == null || !"layout".equals(layout.getNodeName())) {
92             // The child is not layout element
93             return false;
94         }
95         NodeList layoutChildren = layout.getChildNodes();
96         if (layoutChildren == null) {
97             // The 'layout' element has no child.
98             return false;
99         }
100         int num = layoutChildren.getLength();
101         if (num <= 0) {
102             // The 'layout' element has no child.
103             return false;
104         }
105         for (int i = 0; i < num; i++) {
106             Node layoutChild = layoutChildren.item(i);
107             if (layoutChild == null) {
108                 // The 'layout' child is null.
109                 return false;
110             }
111             String name = layoutChild.getNodeName();
112             if ("root-layout".equals(name)) {
113                 continue;
114             } else if ("region".equals(name)) {
115                 NamedNodeMap map = layoutChild.getAttributes();
116                 for (int j = 0; j < map.getLength(); j++) {
117                     Node node = map.item(j);
118                     if (node == null) {
119                         return false;
120                     }
121                     String attrName = node.getNodeName();
122                     // The attr should be one of left, top, height, width, fit and id
123                     if ("left".equals(attrName) || "top".equals(attrName) ||
124                             "height".equals(attrName) || "width".equals(attrName) ||
125                             "fit".equals(attrName)) {
126                         continue;
127                     } else if ("id".equals(attrName)) {
128                         String value;
129                         if (node instanceof AttrImpl) {
130                             value = ((AttrImpl)node).getValue();
131                         } else {
132                             return false;
133                         }
134                         if ("Text".equals(value) || "Image".equals(value)) {
135                             continue;
136                         } else {
137                             // The id attr is not 'Text' or 'Image'
138                             return false;
139                         }
140                     } else {
141                         return false;
142                     }
143                 }
144             } else {
145                 // The 'layout' element has the child other than 'root-layout' or 'region'
146                 return false;
147             }
148         }
149         return true;
150     }
151
152     @Override
153     public void onCreate(Bundle icicle) {
154         super.onCreate(icicle);
155         mHandler = new Handler();
156
157         // Play slide-show in full-screen mode.
158         requestWindowFeature(Window.FEATURE_NO_TITLE);
159         getWindow().setFormat(PixelFormat.TRANSLUCENT);
160         setContentView(R.layout.slideshow);
161
162         Intent intent = getIntent();
163         Uri msg = intent.getData();
164         final SlideshowModel model;
165
166         try {
167             model = SlideshowModel.createFromMessageUri(this, msg);
168         } catch (MmsException e) {
169             Log.e(TAG, "Cannot present the slide show.", e);
170             finish();
171             return;
172         }
173
174         mSlideView = (SlideView) findViewById(R.id.slide_view);
175         PresenterFactory.getPresenter("SlideshowPresenter", this, mSlideView, model);
176
177         mHandler.post(new Runnable() {
178             private boolean isRotating() {
179                 return mSmilPlayer.isPausedState()
180                         || mSmilPlayer.isPlayingState()
181                         || mSmilPlayer.isPlayedState();
182             }
183
184             public void run() {
185                 mSmilPlayer = SmilPlayer.getPlayer();
186                 initMediaController();
187                 mSlideView.setMediaController(mMediaController);
188                 // Use SmilHelper.getDocument() to ensure rebuilding the
189                 // entire SMIL document.
190                 mSmilDoc = SmilHelper.getDocument(model);
191                 if (isMMSConformance(mSmilDoc)) {
192                     int imageLeft = 0;
193                     int imageTop = 0;
194                     int textLeft = 0;
195                     int textTop = 0;
196                     LayoutModel layout = model.getLayout();
197                     if (layout != null) {
198                         RegionModel imageRegion = layout.getImageRegion();
199                         if (imageRegion != null) {
200                             imageLeft = imageRegion.getLeft();
201                             imageTop = imageRegion.getTop();
202                         }
203                         RegionModel textRegion = layout.getTextRegion();
204                         if (textRegion != null) {
205                             textLeft = textRegion.getLeft();
206                             textTop = textRegion.getTop();
207                         }
208                     }
209                     mSlideView.enableMMSConformanceMode(textLeft, textTop, imageLeft, imageTop);
210                 }
211                 if (DEBUG) {
212                     ByteArrayOutputStream ostream = new ByteArrayOutputStream();
213                     SmilXmlSerializer.serialize(mSmilDoc, ostream);
214                     if (LOCAL_LOGV) {
215                         Log.v(TAG, ostream.toString());
216                     }
217                 }
218
219                 // Add event listener.
220                 ((EventTarget) mSmilDoc).addEventListener(
221                         SmilDocumentImpl.SMIL_DOCUMENT_END_EVENT,
222                         SlideshowActivity.this, false);
223
224                 mSmilPlayer.init(mSmilDoc);
225                 if (isRotating()) {
226                     mSmilPlayer.reload();
227                 } else {
228                     mSmilPlayer.play();
229                 }
230             }
231         });
232     }
233
234     private void initMediaController() {
235         mMediaController = new MediaController(SlideshowActivity.this, false);
236         mMediaController.setMediaPlayer(new SmilPlayerController(mSmilPlayer));
237         mMediaController.setAnchorView(findViewById(R.id.slide_view));
238         mMediaController.setPrevNextListeners(
239             new OnClickListener() {
240               public void onClick(View v) {
241                   mSmilPlayer.next();
242               }
243             },
244             new OnClickListener() {
245               public void onClick(View v) {
246                   mSmilPlayer.prev();
247               }
248             });
249     }
250
251     @Override
252     public boolean onTouchEvent(MotionEvent ev) {
253         if ((mSmilPlayer != null) && (mMediaController != null)) {
254             mMediaController.show();
255         }
256         return false;
257     }
258
259     @Override
260     protected void onPause() {
261         super.onPause();
262         if (mSmilDoc != null) {
263             ((EventTarget) mSmilDoc).removeEventListener(
264                     SmilDocumentImpl.SMIL_DOCUMENT_END_EVENT, this, false);
265         }
266     }
267
268     @Override
269     protected void onStop() {
270         super.onStop();
271         if ((null != mSmilPlayer)) {
272             if (isFinishing()) {
273                 mSmilPlayer.stop();
274             } else {
275                 mSmilPlayer.stopWhenReload();
276             }
277             if (mMediaController != null) {
278                 // Must do this so we don't leak a window.
279                 mMediaController.hide();
280             }
281         }
282     }
283
284     @Override
285     public boolean onKeyDown(int keyCode, KeyEvent event) {
286         switch (keyCode) {
287             case KeyEvent.KEYCODE_VOLUME_DOWN:
288             case KeyEvent.KEYCODE_VOLUME_UP:
289             case KeyEvent.KEYCODE_DPAD_UP:
290             case KeyEvent.KEYCODE_DPAD_DOWN:
291             case KeyEvent.KEYCODE_DPAD_LEFT:
292             case KeyEvent.KEYCODE_DPAD_RIGHT:
293                 break;
294             case KeyEvent.KEYCODE_BACK:
295             case KeyEvent.KEYCODE_MENU:
296                 if ((mSmilPlayer != null) &&
297                         (mSmilPlayer.isPausedState()
298                         || mSmilPlayer.isPlayingState()
299                         || mSmilPlayer.isPlayedState())) {
300                     mSmilPlayer.stop();
301                 }
302                 break;
303             default:
304                 if ((mSmilPlayer != null) && (mMediaController != null)) {
305                     mMediaController.show();
306                 }
307         }
308         return super.onKeyDown(keyCode, event);
309     }
310
311     private class SmilPlayerController implements MediaPlayerControl {
312         private final SmilPlayer mPlayer;
313
314         public SmilPlayerController(SmilPlayer player) {
315             mPlayer = player;
316         }
317
318         public int getBufferPercentage() {
319             // We don't need to buffer data, always return 100%.
320             return 100;
321         }
322
323         public int getCurrentPosition() {
324             return mPlayer.getCurrentPosition();
325         }
326
327         public int getDuration() {
328             return mPlayer.getDuration();
329         }
330
331         public boolean isPlaying() {
332             return mPlayer != null ? mPlayer.isPlayingState() : false;
333         }
334
335         public void pause() {
336             if (mPlayer != null) {
337                 mPlayer.pause();
338             }
339         }
340
341         public void seekTo(int pos) {
342             // Don't need to support.
343         }
344
345         public void start() {
346             if (mPlayer != null) {
347                 mPlayer.start();
348             }
349         }
350
351         public boolean canPause() {
352             return true;
353         }
354
355         public boolean canSeekBackward() {
356             return true;
357         }
358
359         public boolean canSeekForward() {
360             return true;
361         }
362     }
363
364     public void handleEvent(Event evt) {
365         final Event event = evt;
366         mHandler.post(new Runnable() {
367             public void run() {
368                 String type = event.getType();
369                 if(type.equals(SmilDocumentImpl.SMIL_DOCUMENT_END_EVENT)) {
370                     finish();
371                 }
372             }
373         });
374     }
375 }