1f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin/*
2f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Copyright (C) 2010 The Android Open Source Project
3f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin *
4f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Licensed under the Apache License, Version 2.0 (the "License");
5f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * you may not use this file except in compliance with the License.
6f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * You may obtain a copy of the License at
7f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin *
8f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin *      http://www.apache.org/licenses/LICENSE-2.0
9f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin *
10f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Unless required by applicable law or agreed to in writing, software
11f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * distributed under the License is distributed on an "AS IS" BASIS,
12f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * See the License for the specific language governing permissions and
14f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * limitations under the License.
15f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin */
16f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
17f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linpackage com.android.gallery3d.app;
18f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
19604f053d040782159b61d3b74ee533bc2c0ccdd0Ray Chenimport android.app.Activity;
20604f053d040782159b61d3b74ee533bc2c0ccdd0Ray Chenimport android.content.Intent;
21604f053d040782159b61d3b74ee533bc2c0ccdd0Ray Chenimport android.graphics.Bitmap;
22604f053d040782159b61d3b74ee533bc2c0ccdd0Ray Chenimport android.os.Bundle;
23604f053d040782159b61d3b74ee533bc2c0ccdd0Ray Chenimport android.os.Handler;
24604f053d040782159b61d3b74ee533bc2c0ccdd0Ray Chenimport android.os.Message;
25604f053d040782159b61d3b74ee533bc2c0ccdd0Ray Chenimport android.view.MotionEvent;
26604f053d040782159b61d3b74ee533bc2c0ccdd0Ray Chen
27915c2c5b2c367df71599370613af0924bd7c4887Bobby Georgescuimport com.android.gallery3d.R;
28f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.common.Utils;
29f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.data.ContentListener;
30f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.data.MediaItem;
31f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.data.MediaObject;
32f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.data.MediaSet;
33604f053d040782159b61d3b74ee533bc2c0ccdd0Ray Chenimport com.android.gallery3d.data.Path;
34a4eae1abb4f2547dfbda84301ee764ce35464881John Reckimport com.android.gallery3d.glrenderer.GLCanvas;
35f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.ui.GLView;
36f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.ui.SlideshowView;
37f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.ui.SynchronizedHandler;
38f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.util.Future;
39f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.util.FutureListener;
40f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
41f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.util.ArrayList;
42f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.util.Random;
43f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
44f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linpublic class SlideshowPage extends ActivityState {
45f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static final String TAG = "SlideshowPage";
46f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
47f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public static final String KEY_SET_PATH = "media-set-path";
48f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public static final String KEY_ITEM_PATH = "media-item-path";
49f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public static final String KEY_PHOTO_INDEX = "photo-index";
50f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public static final String KEY_RANDOM_ORDER = "random-order";
51f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public static final String KEY_REPEAT = "repeat";
52afb3d1d8f341620f6b69d47d52b515f53817aa91Yuli Huang    public static final String KEY_DREAM = "dream";
53f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
54f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static final long SLIDESHOW_DELAY = 3000; // 3 seconds
55f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
56f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static final int MSG_LOAD_NEXT_BITMAP = 1;
57f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static final int MSG_SHOW_PENDING_BITMAP = 2;
58f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
59f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public static interface Model {
60f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public void pause();
61604f053d040782159b61d3b74ee533bc2c0ccdd0Ray Chen
62f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public void resume();
63604f053d040782159b61d3b74ee533bc2c0ccdd0Ray Chen
64f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public Future<Slide> nextSlide(FutureListener<Slide> listener);
65f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
66f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
67f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public static class Slide {
68f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public Bitmap bitmap;
69f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public MediaItem item;
70f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public int index;
71f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
72f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public Slide(MediaItem item, int index, Bitmap bitmap) {
73f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            this.bitmap = bitmap;
74f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            this.item = item;
75f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            this.index = index;
76f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
77f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
78f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
79f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private Handler mHandler;
80f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private Model mModel;
81f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private SlideshowView mSlideshowView;
82f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
83f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private Slide mPendingSlide = null;
84f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private boolean mIsActive = false;
85604f053d040782159b61d3b74ee533bc2c0ccdd0Ray Chen    private final Intent mResultIntent = new Intent();
86f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
87915c2c5b2c367df71599370613af0924bd7c4887Bobby Georgescu    @Override
88915c2c5b2c367df71599370613af0924bd7c4887Bobby Georgescu    protected int getBackgroundColorId() {
89915c2c5b2c367df71599370613af0924bd7c4887Bobby Georgescu        return R.color.slideshow_background;
90915c2c5b2c367df71599370613af0924bd7c4887Bobby Georgescu    }
91915c2c5b2c367df71599370613af0924bd7c4887Bobby Georgescu
92604f053d040782159b61d3b74ee533bc2c0ccdd0Ray Chen    private final GLView mRootPane = new GLView() {
93f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        @Override
94604f053d040782159b61d3b74ee533bc2c0ccdd0Ray Chen        protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
95f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mSlideshowView.layout(0, 0, right - left, bottom - top);
96f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
97f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
98f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        @Override
99f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        protected boolean onTouch(MotionEvent event) {
100f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            if (event.getAction() == MotionEvent.ACTION_UP) {
101f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                onBackPressed();
102f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
103f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            return true;
104f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
105f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
106f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        @Override
107f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        protected void renderBackground(GLCanvas canvas) {
108915c2c5b2c367df71599370613af0924bd7c4887Bobby Georgescu            canvas.clearBuffer(getBackgroundColor());
109f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
110f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    };
111f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
112f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @Override
113f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public void onCreate(Bundle data, Bundle restoreState) {
11445c56f2d34c71d0bc9b84ebeef6d1314738d0fc0Bobby Georgescu        super.onCreate(data, restoreState);
115ef132358deba6acbbeaf0a63014c77c98bca1d9aBobby Georgescu        mFlags |= (FLAG_HIDE_ACTION_BAR | FLAG_HIDE_STATUS_BAR);
116afb3d1d8f341620f6b69d47d52b515f53817aa91Yuli Huang        if (data.getBoolean(KEY_DREAM)) {
117afb3d1d8f341620f6b69d47d52b515f53817aa91Yuli Huang            // Dream screensaver only keeps screen on for plugged devices.
1184a10c9782bc397ab3b77e5d7a439a90169484b1aDoris Liu            mFlags |= FLAG_SCREEN_ON_WHEN_PLUGGED | FLAG_SHOW_WHEN_LOCKED;
119afb3d1d8f341620f6b69d47d52b515f53817aa91Yuli Huang        } else {
120afb3d1d8f341620f6b69d47d52b515f53817aa91Yuli Huang            // User-initiated slideshow would always keep screen on.
121afb3d1d8f341620f6b69d47d52b515f53817aa91Yuli Huang            mFlags |= FLAG_SCREEN_ON_ALWAYS;
122afb3d1d8f341620f6b69d47d52b515f53817aa91Yuli Huang        }
123f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
124f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mHandler = new SynchronizedHandler(mActivity.getGLRoot()) {
125f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            @Override
126f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            public void handleMessage(Message message) {
127f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                switch (message.what) {
128f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    case MSG_SHOW_PENDING_BITMAP:
129f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                        showPendingBitmap();
130f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                        break;
131f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    case MSG_LOAD_NEXT_BITMAP:
132f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                        loadNextBitmap();
133f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                        break;
134f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    default: throw new AssertionError();
135f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                }
136f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
137f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        };
138f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        initializeViews();
139f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        initializeData(data);
140f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
141f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
142f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private void loadNextBitmap() {
143f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mModel.nextSlide(new FutureListener<Slide>() {
1447817979db0c52ffeacb951625b1e821eba303285Ahbong Chang            @Override
145f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            public void onFutureDone(Future<Slide> future) {
146f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                mPendingSlide = future.get();
147f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                mHandler.sendEmptyMessage(MSG_SHOW_PENDING_BITMAP);
148f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
149f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        });
150f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
151f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
152f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private void showPendingBitmap() {
153f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        // mPendingBitmap could be null, if
154604f053d040782159b61d3b74ee533bc2c0ccdd0Ray Chen        // 1.) there is no more items
155604f053d040782159b61d3b74ee533bc2c0ccdd0Ray Chen        // 2.) mModel is paused
156f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        Slide slide = mPendingSlide;
157f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (slide == null) {
158f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            if (mIsActive) {
159f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                mActivity.getStateManager().finishState(SlideshowPage.this);
160f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
161f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            return;
162f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
163f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
164f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mSlideshowView.next(slide.bitmap, slide.item.getRotation());
165f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
166f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        setStateResult(Activity.RESULT_OK, mResultIntent
167f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                .putExtra(KEY_ITEM_PATH, slide.item.getPath().toString())
168f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                .putExtra(KEY_PHOTO_INDEX, slide.index));
169604f053d040782159b61d3b74ee533bc2c0ccdd0Ray Chen        mHandler.sendEmptyMessageDelayed(MSG_LOAD_NEXT_BITMAP, SLIDESHOW_DELAY);
170f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
171f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
172f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @Override
173f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public void onPause() {
174f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        super.onPause();
175f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mIsActive = false;
176f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mModel.pause();
177f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mSlideshowView.release();
178f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
179f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mHandler.removeMessages(MSG_LOAD_NEXT_BITMAP);
180f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mHandler.removeMessages(MSG_SHOW_PENDING_BITMAP);
181f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
182f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
183f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @Override
184f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public void onResume() {
185f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        super.onResume();
186f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mIsActive = true;
187f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mModel.resume();
188f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
189f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (mPendingSlide != null) {
190f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            showPendingBitmap();
191f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        } else {
192f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            loadNextBitmap();
193f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
194f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
195f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
196f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private void initializeData(Bundle data) {
197f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        boolean random = data.getBoolean(KEY_RANDOM_ORDER, false);
19878979fc21d1e1111a504cc07ae6b0e0bc4d61447Chih-Chung Chang
19978979fc21d1e1111a504cc07ae6b0e0bc4d61447Chih-Chung Chang        // We only want to show slideshow for images only, not videos.
20078979fc21d1e1111a504cc07ae6b0e0bc4d61447Chih-Chung Chang        String mediaPath = data.getString(KEY_SET_PATH);
201604f053d040782159b61d3b74ee533bc2c0ccdd0Ray Chen        mediaPath = FilterUtils.newFilterPath(mediaPath, FilterUtils.FILTER_IMAGE_ONLY);
202f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        MediaSet mediaSet = mActivity.getDataManager().getMediaSet(mediaPath);
203f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
204f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (random) {
205f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            boolean repeat = data.getBoolean(KEY_REPEAT);
206604f053d040782159b61d3b74ee533bc2c0ccdd0Ray Chen            mModel = new SlideshowDataAdapter(mActivity,
207604f053d040782159b61d3b74ee533bc2c0ccdd0Ray Chen                    new ShuffleSource(mediaSet, repeat), 0, null);
208604f053d040782159b61d3b74ee533bc2c0ccdd0Ray Chen            setStateResult(Activity.RESULT_OK, mResultIntent.putExtra(KEY_PHOTO_INDEX, 0));
209f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        } else {
210f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            int index = data.getInt(KEY_PHOTO_INDEX);
211506200619672fa8221b98d50efbe77c777fae3e9Ray Chen            String itemPath = data.getString(KEY_ITEM_PATH);
212506200619672fa8221b98d50efbe77c777fae3e9Ray Chen            Path path = itemPath != null ? Path.fromString(itemPath) : null;
213f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            boolean repeat = data.getBoolean(KEY_REPEAT);
214604f053d040782159b61d3b74ee533bc2c0ccdd0Ray Chen            mModel = new SlideshowDataAdapter(mActivity, new SequentialSource(mediaSet, repeat),
215604f053d040782159b61d3b74ee533bc2c0ccdd0Ray Chen                    index, path);
216604f053d040782159b61d3b74ee533bc2c0ccdd0Ray Chen            setStateResult(Activity.RESULT_OK, mResultIntent.putExtra(KEY_PHOTO_INDEX, index));
217f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
218f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
219f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
220f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private void initializeViews() {
221f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mSlideshowView = new SlideshowView();
222f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mRootPane.addComponent(mSlideshowView);
223f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        setContentPane(mRootPane);
224f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
225f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
226f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static MediaItem findMediaItem(MediaSet mediaSet, int index) {
227f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        for (int i = 0, n = mediaSet.getSubMediaSetCount(); i < n; ++i) {
228f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            MediaSet subset = mediaSet.getSubMediaSet(i);
229f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            int count = subset.getTotalMediaItemCount();
230f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            if (index < count) {
231f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                return findMediaItem(subset, index);
232f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
233f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            index -= count;
234f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
235f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        ArrayList<MediaItem> list = mediaSet.getMediaItem(index, 1);
236f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        return list.isEmpty() ? null : list.get(0);
237f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
238f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
239f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static class ShuffleSource implements SlideshowDataAdapter.SlideshowSource {
240f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        private static final int RETRY_COUNT = 5;
241f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        private final MediaSet mMediaSet;
242f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        private final Random mRandom = new Random();
243f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        private int mOrder[] = new int[0];
244604f053d040782159b61d3b74ee533bc2c0ccdd0Ray Chen        private final boolean mRepeat;
245f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        private long mSourceVersion = MediaSet.INVALID_DATA_VERSION;
246f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        private int mLastIndex = -1;
247f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
248f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public ShuffleSource(MediaSet mediaSet, boolean repeat) {
249f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mMediaSet = Utils.checkNotNull(mediaSet);
250f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mRepeat = repeat;
251f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
252f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
2537817979db0c52ffeacb951625b1e821eba303285Ahbong Chang        @Override
254604f053d040782159b61d3b74ee533bc2c0ccdd0Ray Chen        public int findItemIndex(Path path, int hint) {
255604f053d040782159b61d3b74ee533bc2c0ccdd0Ray Chen            return hint;
256604f053d040782159b61d3b74ee533bc2c0ccdd0Ray Chen        }
257604f053d040782159b61d3b74ee533bc2c0ccdd0Ray Chen
2587817979db0c52ffeacb951625b1e821eba303285Ahbong Chang        @Override
259f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public MediaItem getMediaItem(int index) {
260f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            if (!mRepeat && index >= mOrder.length) return null;
26178979fc21d1e1111a504cc07ae6b0e0bc4d61447Chih-Chung Chang            if (mOrder.length == 0) return null;
262f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mLastIndex = mOrder[index % mOrder.length];
263f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            MediaItem item = findMediaItem(mMediaSet, mLastIndex);
264f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            for (int i = 0; i < RETRY_COUNT && item == null; ++i) {
265f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                Log.w(TAG, "fail to find image: " + mLastIndex);
266f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                mLastIndex = mRandom.nextInt(mOrder.length);
267f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                item = findMediaItem(mMediaSet, mLastIndex);
268f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
269f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            return item;
270f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
271f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
2727817979db0c52ffeacb951625b1e821eba303285Ahbong Chang        @Override
273f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public long reload() {
274705dc819661cb8c8e839a04577b0641bd6caad53John Reck            long version = mMediaSet.reload();
275f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            if (version != mSourceVersion) {
276f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                mSourceVersion = version;
277f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                int count = mMediaSet.getTotalMediaItemCount();
278f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                if (count != mOrder.length) generateOrderArray(count);
279f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
280f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            return version;
281f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
282f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
283f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        private void generateOrderArray(int totalCount) {
284f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            if (mOrder.length != totalCount) {
285f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                mOrder = new int[totalCount];
286f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                for (int i = 0; i < totalCount; ++i) {
287f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    mOrder[i] = i;
288f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                }
289f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
290f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            for (int i = totalCount - 1; i > 0; --i) {
291f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                Utils.swap(mOrder, i, mRandom.nextInt(i + 1));
292f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
293f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            if (mOrder[0] == mLastIndex && totalCount > 1) {
294f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                Utils.swap(mOrder, 0, mRandom.nextInt(totalCount - 1) + 1);
295f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
296f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
297f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
2987817979db0c52ffeacb951625b1e821eba303285Ahbong Chang        @Override
299f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public void addContentListener(ContentListener listener) {
300f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mMediaSet.addContentListener(listener);
301f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
302f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
3037817979db0c52ffeacb951625b1e821eba303285Ahbong Chang        @Override
304f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public void removeContentListener(ContentListener listener) {
305f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mMediaSet.removeContentListener(listener);
306f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
307f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
308f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
309f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static class SequentialSource implements SlideshowDataAdapter.SlideshowSource {
310f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        private static final int DATA_SIZE = 32;
311f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
312f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        private ArrayList<MediaItem> mData = new ArrayList<MediaItem>();
313f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        private int mDataStart = 0;
314f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        private long mDataVersion = MediaObject.INVALID_DATA_VERSION;
315f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        private final MediaSet mMediaSet;
316f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        private final boolean mRepeat;
317f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
318f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public SequentialSource(MediaSet mediaSet, boolean repeat) {
319f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mMediaSet = mediaSet;
320f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mRepeat = repeat;
321f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
322f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
3237817979db0c52ffeacb951625b1e821eba303285Ahbong Chang        @Override
324604f053d040782159b61d3b74ee533bc2c0ccdd0Ray Chen        public int findItemIndex(Path path, int hint) {
325604f053d040782159b61d3b74ee533bc2c0ccdd0Ray Chen            return mMediaSet.getIndexOfItem(path, hint);
326604f053d040782159b61d3b74ee533bc2c0ccdd0Ray Chen        }
327604f053d040782159b61d3b74ee533bc2c0ccdd0Ray Chen
3287817979db0c52ffeacb951625b1e821eba303285Ahbong Chang        @Override
329f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public MediaItem getMediaItem(int index) {
330f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            int dataEnd = mDataStart + mData.size();
331f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
332f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            if (mRepeat) {
33378979fc21d1e1111a504cc07ae6b0e0bc4d61447Chih-Chung Chang                int count = mMediaSet.getMediaItemCount();
33478979fc21d1e1111a504cc07ae6b0e0bc4d61447Chih-Chung Chang                if (count == 0) return null;
33578979fc21d1e1111a504cc07ae6b0e0bc4d61447Chih-Chung Chang                index = index % count;
336f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
337f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            if (index < mDataStart || index >= dataEnd) {
338f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                mData = mMediaSet.getMediaItem(index, DATA_SIZE);
339f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                mDataStart = index;
340f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                dataEnd = index + mData.size();
341f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
342f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
343604f053d040782159b61d3b74ee533bc2c0ccdd0Ray Chen            return (index < mDataStart || index >= dataEnd) ? null : mData.get(index - mDataStart);
344f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
345f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
3467817979db0c52ffeacb951625b1e821eba303285Ahbong Chang        @Override
347f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public long reload() {
348705dc819661cb8c8e839a04577b0641bd6caad53John Reck            long version = mMediaSet.reload();
349f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            if (version != mDataVersion) {
350f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                mDataVersion = version;
351f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                mData.clear();
352f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
353f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            return mDataVersion;
354f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
355f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
3567817979db0c52ffeacb951625b1e821eba303285Ahbong Chang        @Override
357f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public void addContentListener(ContentListener listener) {
358f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mMediaSet.addContentListener(listener);
359f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
360f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
3617817979db0c52ffeacb951625b1e821eba303285Ahbong Chang        @Override
362f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public void removeContentListener(ContentListener listener) {
363f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mMediaSet.removeContentListener(listener);
364f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
365f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
366f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin}
367