172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project/*
272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * Copyright (C) 2008 Esmertec AG.
372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project *
572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * you may not use this file except in compliance with the License.
772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * You may obtain a copy of the License at
872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project *
972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
1072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project *
1172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software
1272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
1372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * See the License for the specific language governing permissions and
1572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * limitations under the License.
1672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project */
1772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
1872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectpackage com.android.mms.ui;
1972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
20d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport java.io.ByteArrayOutputStream;
2172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
22d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Taoimport org.w3c.dom.NamedNodeMap;
23d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Taoimport org.w3c.dom.Node;
24d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Taoimport org.w3c.dom.NodeList;
2572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport org.w3c.dom.events.Event;
2672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport org.w3c.dom.events.EventListener;
2772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport org.w3c.dom.events.EventTarget;
2872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport org.w3c.dom.smil.SMILDocument;
29d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Taoimport org.w3c.dom.smil.SMILElement;
3072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
3172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.app.Activity;
3272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.content.Intent;
3372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.graphics.PixelFormat;
3472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.net.Uri;
3572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.os.Bundle;
3672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.os.Handler;
3772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.util.Log;
3872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.view.KeyEvent;
3972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.view.MotionEvent;
40d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Taoimport android.view.View;
41d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Taoimport android.view.View.OnClickListener;
42d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport android.view.Window;
4372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.widget.MediaController;
4472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.widget.MediaController.MediaPlayerControl;
45828f0d230982a0bddb4ad1e67150ccac08c1bb58Frederic Predonimport android.widget.SeekBar;
4672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
47d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.R;
48d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.dom.AttrImpl;
49d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.dom.smil.SmilDocumentImpl;
50d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.dom.smil.SmilPlayer;
51d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.dom.smil.parser.SmilXmlSerializer;
52d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.model.LayoutModel;
53d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.model.RegionModel;
54d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.model.SlideshowModel;
55d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.model.SmilHelper;
56d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.google.android.mms.MmsException;
5772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
5872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project/**
5972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * Plays the given slideshow in full-screen mode with a common controller.
6072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project */
6172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectpublic class SlideshowActivity extends Activity implements EventListener {
6272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final String TAG = "SlideshowActivity";
6372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final boolean DEBUG = false;
64150c4179995cc0a75f934ef194372f9295957ca2Joe Onorato    private static final boolean LOCAL_LOGV = false;
6572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
6672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private MediaController mMediaController;
6772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private SmilPlayer mSmilPlayer;
6872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
6972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private Handler mHandler;
7072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
7172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private SMILDocument mSmilDoc;
7272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
73d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao    private SlideView mSlideView;
74257690a737bec08d4dc445c92075e0ff84a66bc7Tom Taylor    private int mSlideCount;
75d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao
76d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao    /**
77d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao     * @return whether the Smil has MMS conformance layout.
78d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao     * Refer to MMS Conformance Document OMA-MMS-CONF-v1_2-20050301-A
79d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao     */
80d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao    private static final boolean isMMSConformance(SMILDocument smilDoc) {
81d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao        SMILElement head = smilDoc.getHead();
82d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao        if (head == null) {
83d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao            // No 'head' element
84d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao            return false;
85d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao        }
86d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao        NodeList children = head.getChildNodes();
87d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao        if (children == null || children.getLength() != 1) {
88d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao            // The 'head' element should have only one child.
89d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao            return false;
90d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao        }
91d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao        Node layout = children.item(0);
92d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao        if (layout == null || !"layout".equals(layout.getNodeName())) {
93d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao            // The child is not layout element
94d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao            return false;
95d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao        }
96d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao        NodeList layoutChildren = layout.getChildNodes();
97d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao        if (layoutChildren == null) {
98d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao            // The 'layout' element has no child.
99d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao            return false;
100d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao        }
101d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao        int num = layoutChildren.getLength();
102d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao        if (num <= 0) {
103d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao            // The 'layout' element has no child.
104d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao            return false;
105d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao        }
106d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao        for (int i = 0; i < num; i++) {
107d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao            Node layoutChild = layoutChildren.item(i);
108d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao            if (layoutChild == null) {
109d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                // The 'layout' child is null.
110d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                return false;
111d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao            }
112d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao            String name = layoutChild.getNodeName();
113d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao            if ("root-layout".equals(name)) {
114d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                continue;
115d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao            } else if ("region".equals(name)) {
116d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                NamedNodeMap map = layoutChild.getAttributes();
117d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                for (int j = 0; j < map.getLength(); j++) {
118d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                    Node node = map.item(j);
119d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                    if (node == null) {
120d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                        return false;
121d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                    }
122d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                    String attrName = node.getNodeName();
123d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                    // The attr should be one of left, top, height, width, fit and id
124d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                    if ("left".equals(attrName) || "top".equals(attrName) ||
125d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                            "height".equals(attrName) || "width".equals(attrName) ||
126d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                            "fit".equals(attrName)) {
127d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                        continue;
128d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                    } else if ("id".equals(attrName)) {
129d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                        String value;
130d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                        if (node instanceof AttrImpl) {
131d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                            value = ((AttrImpl)node).getValue();
132d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                        } else {
133d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                            return false;
134d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                        }
135d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                        if ("Text".equals(value) || "Image".equals(value)) {
136d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                            continue;
137d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                        } else {
138d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                            // The id attr is not 'Text' or 'Image'
139d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                            return false;
140d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                        }
141d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                    } else {
142d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                        return false;
143d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                    }
144d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                }
145d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao            } else {
146d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                // The 'layout' element has the child other than 'root-layout' or 'region'
147d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                return false;
148d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao            }
149d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao        }
150d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao        return true;
151d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao    }
152d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao
15372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    @Override
15472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public void onCreate(Bundle icicle) {
15572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        super.onCreate(icicle);
15672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        mHandler = new Handler();
15772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
15872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // Play slide-show in full-screen mode.
15972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        requestWindowFeature(Window.FEATURE_NO_TITLE);
16072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        getWindow().setFormat(PixelFormat.TRANSLUCENT);
16172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        setContentView(R.layout.slideshow);
16272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
16372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        Intent intent = getIntent();
16472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        Uri msg = intent.getData();
16572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        final SlideshowModel model;
16672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
16772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        try {
16872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            model = SlideshowModel.createFromMessageUri(this, msg);
169257690a737bec08d4dc445c92075e0ff84a66bc7Tom Taylor            mSlideCount = model.size();
17072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        } catch (MmsException e) {
17172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            Log.e(TAG, "Cannot present the slide show.", e);
17272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            finish();
17372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            return;
17472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
17572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
176d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao        mSlideView = (SlideView) findViewById(R.id.slide_view);
177d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao        PresenterFactory.getPresenter("SlideshowPresenter", this, mSlideView, model);
17872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
17972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        mHandler.post(new Runnable() {
18072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            private boolean isRotating() {
18172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                return mSmilPlayer.isPausedState()
18272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        || mSmilPlayer.isPlayingState()
18372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        || mSmilPlayer.isPlayedState();
18472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
18572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
18672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            public void run() {
18772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                mSmilPlayer = SmilPlayer.getPlayer();
188257690a737bec08d4dc445c92075e0ff84a66bc7Tom Taylor                if (mSlideCount > 1) {
189257690a737bec08d4dc445c92075e0ff84a66bc7Tom Taylor                    // Only show the slideshow controller if we have more than a single slide.
190257690a737bec08d4dc445c92075e0ff84a66bc7Tom Taylor                    // Otherwise, when we play a sound on a single slide, it appears like
191257690a737bec08d4dc445c92075e0ff84a66bc7Tom Taylor                    // the slide controller should control the sound (seeking, ff'ing, etc).
192257690a737bec08d4dc445c92075e0ff84a66bc7Tom Taylor                    initMediaController();
193257690a737bec08d4dc445c92075e0ff84a66bc7Tom Taylor                    mSlideView.setMediaController(mMediaController);
194257690a737bec08d4dc445c92075e0ff84a66bc7Tom Taylor                }
19572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                // Use SmilHelper.getDocument() to ensure rebuilding the
19672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                // entire SMIL document.
19772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                mSmilDoc = SmilHelper.getDocument(model);
198d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                if (isMMSConformance(mSmilDoc)) {
199d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                    int imageLeft = 0;
200d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                    int imageTop = 0;
201d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                    int textLeft = 0;
202d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                    int textTop = 0;
203d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                    LayoutModel layout = model.getLayout();
204d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                    if (layout != null) {
205d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                        RegionModel imageRegion = layout.getImageRegion();
206d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                        if (imageRegion != null) {
207d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                            imageLeft = imageRegion.getLeft();
208d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                            imageTop = imageRegion.getTop();
209d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                        }
210d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                        RegionModel textRegion = layout.getTextRegion();
211d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                        if (textRegion != null) {
212d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                            textLeft = textRegion.getLeft();
213d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                            textTop = textRegion.getTop();
214d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                        }
215d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                    }
216d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                    mSlideView.enableMMSConformanceMode(textLeft, textTop, imageLeft, imageTop);
217d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao                }
21872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                if (DEBUG) {
21972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    ByteArrayOutputStream ostream = new ByteArrayOutputStream();
22072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    SmilXmlSerializer.serialize(mSmilDoc, ostream);
22172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    if (LOCAL_LOGV) {
22272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        Log.v(TAG, ostream.toString());
22372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    }
22472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                }
22572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
22672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                // Add event listener.
22772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                ((EventTarget) mSmilDoc).addEventListener(
22872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        SmilDocumentImpl.SMIL_DOCUMENT_END_EVENT,
22972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        SlideshowActivity.this, false);
23072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
23172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                mSmilPlayer.init(mSmilDoc);
23272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                if (isRotating()) {
23372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    mSmilPlayer.reload();
23472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                } else {
23572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    mSmilPlayer.play();
23672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                }
23772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
23872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        });
23972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
24072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
24172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private void initMediaController() {
24272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        mMediaController = new MediaController(SlideshowActivity.this, false);
24372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        mMediaController.setMediaPlayer(new SmilPlayerController(mSmilPlayer));
24472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        mMediaController.setAnchorView(findViewById(R.id.slide_view));
245d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao        mMediaController.setPrevNextListeners(
246d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao            new OnClickListener() {
247b764ab1119f862e033d8b616d9f87ce9a87a87e5Todor Kalaydjiev              public void onClick(View v) {
248b764ab1119f862e033d8b616d9f87ce9a87a87e5Todor Kalaydjiev                  mSmilPlayer.next();
249b764ab1119f862e033d8b616d9f87ce9a87a87e5Todor Kalaydjiev              }
250d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao            },
251d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao            new OnClickListener() {
252b764ab1119f862e033d8b616d9f87ce9a87a87e5Todor Kalaydjiev              public void onClick(View v) {
253b764ab1119f862e033d8b616d9f87ce9a87a87e5Todor Kalaydjiev                  mSmilPlayer.prev();
254b764ab1119f862e033d8b616d9f87ce9a87a87e5Todor Kalaydjiev              }
255d7a1ec4c8a007f707cc3115ed6e558f839f875eaBai Tao            });
25672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
25772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
25872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    @Override
25972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public boolean onTouchEvent(MotionEvent ev) {
26072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if ((mSmilPlayer != null) && (mMediaController != null)) {
26172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            mMediaController.show();
26272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
26372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        return false;
26472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
26572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
26672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    @Override
26772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    protected void onPause() {
26872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        super.onPause();
26972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (mSmilDoc != null) {
27072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            ((EventTarget) mSmilDoc).removeEventListener(
27172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    SmilDocumentImpl.SMIL_DOCUMENT_END_EVENT, this, false);
272a713f75b8d9f7158d7d89e5f7f7f024db3a0ab13Tom Taylor        }
273a713f75b8d9f7158d7d89e5f7f7f024db3a0ab13Tom Taylor        if (mSmilPlayer != null) {
274a713f75b8d9f7158d7d89e5f7f7f024db3a0ab13Tom Taylor            mSmilPlayer.pause();
27572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
27672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
27772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
27872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    @Override
27972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    protected void onStop() {
28072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        super.onStop();
28172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if ((null != mSmilPlayer)) {
28272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            if (isFinishing()) {
28372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                mSmilPlayer.stop();
28472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            } else {
28572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                mSmilPlayer.stopWhenReload();
28672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
287ff408aa9dd640912cf94ae37739d76722b1d2806Tom Taylor            if (mMediaController != null) {
288612ec565b9b76446bd3af6c074f7180d97fa9d7cTom Taylor                // Must set the seek bar change listener null, otherwise if we rotate it
289612ec565b9b76446bd3af6c074f7180d97fa9d7cTom Taylor                // while tapping progress bar continuously, window will leak.
290612ec565b9b76446bd3af6c074f7180d97fa9d7cTom Taylor                View seekBar = mMediaController
291828f0d230982a0bddb4ad1e67150ccac08c1bb58Frederic Predon                        .findViewById(com.android.internal.R.id.mediacontroller_progress);
292612ec565b9b76446bd3af6c074f7180d97fa9d7cTom Taylor                if (seekBar instanceof SeekBar) {
293612ec565b9b76446bd3af6c074f7180d97fa9d7cTom Taylor                    ((SeekBar)seekBar).setOnSeekBarChangeListener(null);
294612ec565b9b76446bd3af6c074f7180d97fa9d7cTom Taylor                }
295ff408aa9dd640912cf94ae37739d76722b1d2806Tom Taylor                // Must do this so we don't leak a window.
296ff408aa9dd640912cf94ae37739d76722b1d2806Tom Taylor                mMediaController.hide();
297ff408aa9dd640912cf94ae37739d76722b1d2806Tom Taylor            }
29872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
29972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
30072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
30172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    @Override
302828f0d230982a0bddb4ad1e67150ccac08c1bb58Frederic Predon    protected void onDestroy() {
303828f0d230982a0bddb4ad1e67150ccac08c1bb58Frederic Predon        if (mSlideView != null) {
304828f0d230982a0bddb4ad1e67150ccac08c1bb58Frederic Predon            mSlideView.setMediaController(null);
305828f0d230982a0bddb4ad1e67150ccac08c1bb58Frederic Predon        }
306828f0d230982a0bddb4ad1e67150ccac08c1bb58Frederic Predon        super.onDestroy();
307828f0d230982a0bddb4ad1e67150ccac08c1bb58Frederic Predon    }
308828f0d230982a0bddb4ad1e67150ccac08c1bb58Frederic Predon
309828f0d230982a0bddb4ad1e67150ccac08c1bb58Frederic Predon    @Override
31072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public boolean onKeyDown(int keyCode, KeyEvent event) {
31172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        switch (keyCode) {
31272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            case KeyEvent.KEYCODE_VOLUME_DOWN:
31372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            case KeyEvent.KEYCODE_VOLUME_UP:
31460cbbe405bffddf13ed723b6d2181d7b93e71fe1Jeff Brown            case KeyEvent.KEYCODE_VOLUME_MUTE:
31572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            case KeyEvent.KEYCODE_DPAD_UP:
31672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            case KeyEvent.KEYCODE_DPAD_DOWN:
31772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            case KeyEvent.KEYCODE_DPAD_LEFT:
31872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            case KeyEvent.KEYCODE_DPAD_RIGHT:
31972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                break;
320bdf926782d291baf6f6b96dd71ad883deb77582fMadhav B            case KeyEvent.KEYCODE_BACK:
321bdf926782d291baf6f6b96dd71ad883deb77582fMadhav B            case KeyEvent.KEYCODE_MENU:
322bdf926782d291baf6f6b96dd71ad883deb77582fMadhav B                if ((mSmilPlayer != null) &&
323bdf926782d291baf6f6b96dd71ad883deb77582fMadhav B                        (mSmilPlayer.isPausedState()
324bdf926782d291baf6f6b96dd71ad883deb77582fMadhav B                        || mSmilPlayer.isPlayingState()
325bdf926782d291baf6f6b96dd71ad883deb77582fMadhav B                        || mSmilPlayer.isPlayedState())) {
326bdf926782d291baf6f6b96dd71ad883deb77582fMadhav B                    mSmilPlayer.stop();
327bdf926782d291baf6f6b96dd71ad883deb77582fMadhav B                }
328bdf926782d291baf6f6b96dd71ad883deb77582fMadhav B                break;
32972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            default:
33072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                if ((mSmilPlayer != null) && (mMediaController != null)) {
33172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    mMediaController.show();
33272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                }
33372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
33472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        return super.onKeyDown(keyCode, event);
33572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
33672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
33772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private class SmilPlayerController implements MediaPlayerControl {
33872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        private final SmilPlayer mPlayer;
339626772e1cf5dc119e127b6519c8143b6691aab4eTodor Kalaydjiev        /**
340626772e1cf5dc119e127b6519c8143b6691aab4eTodor Kalaydjiev         * We need to cache the playback state because when the MediaController issues a play or
341626772e1cf5dc119e127b6519c8143b6691aab4eTodor Kalaydjiev         * pause command, it expects subsequent calls to {@link #isPlaying()} to return the right
342626772e1cf5dc119e127b6519c8143b6691aab4eTodor Kalaydjiev         * value immediately. However, the SmilPlayer executes play and pause asynchronously, so
343626772e1cf5dc119e127b6519c8143b6691aab4eTodor Kalaydjiev         * {@link #isPlaying()} will return the wrong value for some time. That's why we keep our
344626772e1cf5dc119e127b6519c8143b6691aab4eTodor Kalaydjiev         * own version of the state of whether the player is playing.
345626772e1cf5dc119e127b6519c8143b6691aab4eTodor Kalaydjiev         *
346626772e1cf5dc119e127b6519c8143b6691aab4eTodor Kalaydjiev         * Initialized to true because we always programatically start the SmilPlayer upon creation
347626772e1cf5dc119e127b6519c8143b6691aab4eTodor Kalaydjiev         */
348626772e1cf5dc119e127b6519c8143b6691aab4eTodor Kalaydjiev        private boolean mCachedIsPlaying = true;
34972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
35072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        public SmilPlayerController(SmilPlayer player) {
35172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            mPlayer = player;
35272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
35372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
35472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        public int getBufferPercentage() {
35572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            // We don't need to buffer data, always return 100%.
35672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            return 100;
35772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
35872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
35972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        public int getCurrentPosition() {
36072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            return mPlayer.getCurrentPosition();
36172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
36272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
36372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        public int getDuration() {
36472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            return mPlayer.getDuration();
36572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
36672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
36772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        public boolean isPlaying() {
368626772e1cf5dc119e127b6519c8143b6691aab4eTodor Kalaydjiev            return mCachedIsPlaying;
36972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
37072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
37172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        public void pause() {
372626772e1cf5dc119e127b6519c8143b6691aab4eTodor Kalaydjiev            mPlayer.pause();
373626772e1cf5dc119e127b6519c8143b6691aab4eTodor Kalaydjiev            mCachedIsPlaying = false;
37472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
37572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
37672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        public void seekTo(int pos) {
37772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            // Don't need to support.
37872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
37972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
38072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        public void start() {
381626772e1cf5dc119e127b6519c8143b6691aab4eTodor Kalaydjiev            mPlayer.start();
382626772e1cf5dc119e127b6519c8143b6691aab4eTodor Kalaydjiev            mCachedIsPlaying = true;
38372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
384020411c42adb2b7968872d43f5594535aa3acaf4Marco Nelissen
385020411c42adb2b7968872d43f5594535aa3acaf4Marco Nelissen        public boolean canPause() {
386020411c42adb2b7968872d43f5594535aa3acaf4Marco Nelissen            return true;
387020411c42adb2b7968872d43f5594535aa3acaf4Marco Nelissen        }
388020411c42adb2b7968872d43f5594535aa3acaf4Marco Nelissen
389020411c42adb2b7968872d43f5594535aa3acaf4Marco Nelissen        public boolean canSeekBackward() {
390020411c42adb2b7968872d43f5594535aa3acaf4Marco Nelissen            return true;
391020411c42adb2b7968872d43f5594535aa3acaf4Marco Nelissen        }
392020411c42adb2b7968872d43f5594535aa3acaf4Marco Nelissen
393020411c42adb2b7968872d43f5594535aa3acaf4Marco Nelissen        public boolean canSeekForward() {
394020411c42adb2b7968872d43f5594535aa3acaf4Marco Nelissen            return true;
395020411c42adb2b7968872d43f5594535aa3acaf4Marco Nelissen        }
3963c2ce64729072ac1ce0fe77757a1971209b01fddMarco Nelissen
3973c2ce64729072ac1ce0fe77757a1971209b01fddMarco Nelissen        @Override
3983c2ce64729072ac1ce0fe77757a1971209b01fddMarco Nelissen        public int getAudioSessionId() {
3993c2ce64729072ac1ce0fe77757a1971209b01fddMarco Nelissen            return 0;
4003c2ce64729072ac1ce0fe77757a1971209b01fddMarco Nelissen        }
40172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
40272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
40372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public void handleEvent(Event evt) {
40472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        final Event event = evt;
40572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        mHandler.post(new Runnable() {
40672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            public void run() {
40772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                String type = event.getType();
40872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                if(type.equals(SmilDocumentImpl.SMIL_DOCUMENT_END_EVENT)) {
40972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    finish();
41072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                }
41172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
41272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        });
41372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
41472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project}
415