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.ui; 18f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 19dd46fe623b16ba14c70a539b7599cc75c7799612Owen Linimport android.graphics.Bitmap; 20dd46fe623b16ba14c70a539b7599cc75c7799612Owen Linimport android.os.Message; 21dd46fe623b16ba14c70a539b7599cc75c7799612Owen Lin 22b21b8e58a604f6c701245d84b141b5b87663192bOwen Linimport com.android.gallery3d.app.AbstractGalleryActivity; 23c3d8ac3b9504346dafc49e006b5f732dd1db21e8Owen Linimport com.android.gallery3d.app.AlbumDataLoader; 24f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.common.Utils; 25f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.data.MediaItem; 262f060cc74ab6be5e5dd39e53dc99941b368ffb60Doris Liuimport com.android.gallery3d.data.MediaObject; 272f060cc74ab6be5e5dd39e53dc99941b368ffb60Doris Liuimport com.android.gallery3d.data.MediaObject.PanoramaSupportCallback; 28f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescuimport com.android.gallery3d.data.Path; 29a4eae1abb4f2547dfbda84301ee764ce35464881John Reckimport com.android.gallery3d.glrenderer.Texture; 30a4eae1abb4f2547dfbda84301ee764ce35464881John Reckimport com.android.gallery3d.glrenderer.TiledTexture; 31f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.util.Future; 32f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.util.FutureListener; 33113bfc77c4468411da9ae1290553c3be89f8df9aOwen Linimport com.android.gallery3d.util.JobLimiter; 34f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 35c3d8ac3b9504346dafc49e006b5f732dd1db21e8Owen Linpublic class AlbumSlidingWindow implements AlbumDataLoader.DataListener { 36f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @SuppressWarnings("unused") 37f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final String TAG = "AlbumSlidingWindow"; 38f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 391a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin private static final int MSG_UPDATE_ENTRY = 0; 40113bfc77c4468411da9ae1290553c3be89f8df9aOwen Lin private static final int JOB_LIMIT = 2; 41f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 42f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static interface Listener { 43f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void onSizeChanged(int size); 447260f6f74d465520e4497b23fe56f98abb0c15a2Owen Lin public void onContentChanged(); 45f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 46f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 471a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin public static class AlbumEntry { 481a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin public MediaItem item; 491a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin public Path path; 501a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin public boolean isPanorama; 511a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin public int rotation; 521a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin public int mediaType; 531a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin public boolean isWaitDisplayed; 54adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin public TiledTexture bitmapTexture; 551a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin public Texture content; 561a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin private BitmapLoader contentLoader; 572f060cc74ab6be5e5dd39e53dc99941b368ffb60Doris Liu private PanoSupportListener mPanoSupportListener; 581a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin } 591a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin 60c3d8ac3b9504346dafc49e006b5f732dd1db21e8Owen Lin private final AlbumDataLoader mSource; 61d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin private final AlbumEntry mData[]; 62d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin private final SynchronizedHandler mHandler; 63d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin private final JobLimiter mThreadPool; 64adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin private final TiledTexture.Uploader mTileUploader; 65d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin 66f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private int mSize; 67f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 68f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private int mContentStart = 0; 69f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private int mContentEnd = 0; 70f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 71f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private int mActiveStart = 0; 72f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private int mActiveEnd = 0; 73f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 74f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private Listener mListener; 75f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 76f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private int mActiveRequestCount = 0; 77f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private boolean mIsActive = false; 78f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 792f060cc74ab6be5e5dd39e53dc99941b368ffb60Doris Liu private class PanoSupportListener implements PanoramaSupportCallback { 802f060cc74ab6be5e5dd39e53dc99941b368ffb60Doris Liu public final AlbumEntry mEntry; 812f060cc74ab6be5e5dd39e53dc99941b368ffb60Doris Liu public PanoSupportListener (AlbumEntry entry) { 822f060cc74ab6be5e5dd39e53dc99941b368ffb60Doris Liu mEntry = entry; 832f060cc74ab6be5e5dd39e53dc99941b368ffb60Doris Liu } 842f060cc74ab6be5e5dd39e53dc99941b368ffb60Doris Liu @Override 852f060cc74ab6be5e5dd39e53dc99941b368ffb60Doris Liu public void panoramaInfoAvailable(MediaObject mediaObject, boolean isPanorama, 862f060cc74ab6be5e5dd39e53dc99941b368ffb60Doris Liu boolean isPanorama360) { 872f060cc74ab6be5e5dd39e53dc99941b368ffb60Doris Liu if (mEntry != null) mEntry.isPanorama = isPanorama; 882f060cc74ab6be5e5dd39e53dc99941b368ffb60Doris Liu } 892f060cc74ab6be5e5dd39e53dc99941b368ffb60Doris Liu } 902f060cc74ab6be5e5dd39e53dc99941b368ffb60Doris Liu 91b21b8e58a604f6c701245d84b141b5b87663192bOwen Lin public AlbumSlidingWindow(AbstractGalleryActivity activity, 92c3d8ac3b9504346dafc49e006b5f732dd1db21e8Owen Lin AlbumDataLoader source, int cacheSize) { 93c3d8ac3b9504346dafc49e006b5f732dd1db21e8Owen Lin source.setDataListener(this); 94f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mSource = source; 951a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin mData = new AlbumEntry[cacheSize]; 96f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mSize = source.size(); 97f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 98f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mHandler = new SynchronizedHandler(activity.getGLRoot()) { 99f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 100f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void handleMessage(Message message) { 1011a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin Utils.assertTrue(message.what == MSG_UPDATE_ENTRY); 1021a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin ((ThumbnailLoader) message.obj).updateEntry(); 103f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 104f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin }; 105f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 106113bfc77c4468411da9ae1290553c3be89f8df9aOwen Lin mThreadPool = new JobLimiter(activity.getThreadPool(), JOB_LIMIT); 107adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin mTileUploader = new TiledTexture.Uploader(activity.getGLRoot()); 108f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 109f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 110f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void setListener(Listener listener) { 111f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mListener = listener; 112f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 113f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 1141a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin public AlbumEntry get(int slotIndex) { 115cfa105d3934c4dfa14f02b693bfa97c8d17d56a9Chih-Chung Chang if (!isActiveSlot(slotIndex)) { 116cfa105d3934c4dfa14f02b693bfa97c8d17d56a9Chih-Chung Chang Utils.fail("invalid slot: %s outsides (%s, %s)", 117cfa105d3934c4dfa14f02b693bfa97c8d17d56a9Chih-Chung Chang slotIndex, mActiveStart, mActiveEnd); 118cfa105d3934c4dfa14f02b693bfa97c8d17d56a9Chih-Chung Chang } 119f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return mData[slotIndex % mData.length]; 120f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 121f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 122f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public boolean isActiveSlot(int slotIndex) { 123f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return slotIndex >= mActiveStart && slotIndex < mActiveEnd; 124f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 125f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 126f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private void setContentWindow(int contentStart, int contentEnd) { 127f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (contentStart == mContentStart && contentEnd == mContentEnd) return; 128f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 129f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (!mIsActive) { 130f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mContentStart = contentStart; 131f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mContentEnd = contentEnd; 132f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mSource.setActiveWindow(contentStart, contentEnd); 133f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return; 134f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 135f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 136f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (contentStart >= mContentEnd || mContentStart >= contentEnd) { 137f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (int i = mContentStart, n = mContentEnd; i < n; ++i) { 138f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin freeSlotContent(i); 139f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 140f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mSource.setActiveWindow(contentStart, contentEnd); 141f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (int i = contentStart; i < contentEnd; ++i) { 142f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin prepareSlotContent(i); 143f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 144f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } else { 145f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (int i = mContentStart; i < contentStart; ++i) { 146f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin freeSlotContent(i); 147f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 148f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (int i = contentEnd, n = mContentEnd; i < n; ++i) { 149f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin freeSlotContent(i); 150f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 151f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mSource.setActiveWindow(contentStart, contentEnd); 152f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (int i = contentStart, n = mContentStart; i < n; ++i) { 153f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin prepareSlotContent(i); 154f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 155f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (int i = mContentEnd; i < contentEnd; ++i) { 156f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin prepareSlotContent(i); 157f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 158f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 159f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 160f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mContentStart = contentStart; 161f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mContentEnd = contentEnd; 162f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 163f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 164f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void setActiveWindow(int start, int end) { 165cfa105d3934c4dfa14f02b693bfa97c8d17d56a9Chih-Chung Chang if (!(start <= end && end - start <= mData.length && end <= mSize)) { 166cfa105d3934c4dfa14f02b693bfa97c8d17d56a9Chih-Chung Chang Utils.fail("%s, %s, %s, %s", start, end, mData.length, mSize); 167cfa105d3934c4dfa14f02b693bfa97c8d17d56a9Chih-Chung Chang } 1681a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin AlbumEntry data[] = mData; 169f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 170f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mActiveStart = start; 171f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mActiveEnd = end; 172f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 173f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int contentStart = Utils.clamp((start + end) / 2 - data.length / 2, 174f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 0, Math.max(0, mSize - data.length)); 175f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int contentEnd = Math.min(contentStart + data.length, mSize); 176f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin setContentWindow(contentStart, contentEnd); 177cd36bfc52cc4e7f4b667ba3c5e8eb950647ae9d1Owen Lin updateTextureUploadQueue(); 178f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mIsActive) updateAllImageRequests(); 179f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 180f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 181cd36bfc52cc4e7f4b667ba3c5e8eb950647ae9d1Owen Lin private void uploadBgTextureInSlot(int index) { 182cd36bfc52cc4e7f4b667ba3c5e8eb950647ae9d1Owen Lin if (index < mContentEnd && index >= mContentStart) { 183cd36bfc52cc4e7f4b667ba3c5e8eb950647ae9d1Owen Lin AlbumEntry entry = mData[index % mData.length]; 1843535d67239b1b1e4ee038f39dece64545b78f2edOwen Lin if (entry.bitmapTexture != null) { 185adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin mTileUploader.addTexture(entry.bitmapTexture); 186cd36bfc52cc4e7f4b667ba3c5e8eb950647ae9d1Owen Lin } 187d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin } 188d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin } 189d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin 190cd36bfc52cc4e7f4b667ba3c5e8eb950647ae9d1Owen Lin private void updateTextureUploadQueue() { 191d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin if (!mIsActive) return; 192adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin mTileUploader.clear(); 193cd36bfc52cc4e7f4b667ba3c5e8eb950647ae9d1Owen Lin 194cd36bfc52cc4e7f4b667ba3c5e8eb950647ae9d1Owen Lin // add foreground textures 195cd36bfc52cc4e7f4b667ba3c5e8eb950647ae9d1Owen Lin for (int i = mActiveStart, n = mActiveEnd; i < n; ++i) { 196d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin AlbumEntry entry = mData[i % mData.length]; 1973535d67239b1b1e4ee038f39dece64545b78f2edOwen Lin if (entry.bitmapTexture != null) { 198adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin mTileUploader.addTexture(entry.bitmapTexture); 199cd36bfc52cc4e7f4b667ba3c5e8eb950647ae9d1Owen Lin } 200cd36bfc52cc4e7f4b667ba3c5e8eb950647ae9d1Owen Lin } 201cd36bfc52cc4e7f4b667ba3c5e8eb950647ae9d1Owen Lin 202cd36bfc52cc4e7f4b667ba3c5e8eb950647ae9d1Owen Lin // add background textures 203cd36bfc52cc4e7f4b667ba3c5e8eb950647ae9d1Owen Lin int range = Math.max( 204cd36bfc52cc4e7f4b667ba3c5e8eb950647ae9d1Owen Lin (mContentEnd - mActiveEnd), (mActiveStart - mContentStart)); 205cd36bfc52cc4e7f4b667ba3c5e8eb950647ae9d1Owen Lin for (int i = 0; i < range; ++i) { 206cd36bfc52cc4e7f4b667ba3c5e8eb950647ae9d1Owen Lin uploadBgTextureInSlot(mActiveEnd + i); 207cd36bfc52cc4e7f4b667ba3c5e8eb950647ae9d1Owen Lin uploadBgTextureInSlot(mActiveStart - i - 1); 208d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin } 209d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin } 210d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin 211f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // We would like to request non active slots in the following order: 212f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // Order: 8 6 4 2 1 3 5 7 213f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // |---------|---------------|---------| 214f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // |<- active ->| 215f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // |<-------- cached range ----------->| 216f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private void requestNonactiveImages() { 217f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int range = Math.max( 218f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin (mContentEnd - mActiveEnd), (mActiveStart - mContentStart)); 219f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (int i = 0 ;i < range; ++i) { 2201a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin requestSlotImage(mActiveEnd + i); 2211a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin requestSlotImage(mActiveStart - 1 - i); 222f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 223f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 224f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 2251a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin // return whether the request is in progress or not 2261a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin private boolean requestSlotImage(int slotIndex) { 2271a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin if (slotIndex < mContentStart || slotIndex >= mContentEnd) return false; 2281a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin AlbumEntry entry = mData[slotIndex % mData.length]; 2291a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin if (entry.content != null || entry.item == null) return false; 2301a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin 2312f060cc74ab6be5e5dd39e53dc99941b368ffb60Doris Liu // Set up the panorama callback 2322f060cc74ab6be5e5dd39e53dc99941b368ffb60Doris Liu entry.mPanoSupportListener = new PanoSupportListener(entry); 2332f060cc74ab6be5e5dd39e53dc99941b368ffb60Doris Liu entry.item.getPanoramaSupport(entry.mPanoSupportListener); 2342f060cc74ab6be5e5dd39e53dc99941b368ffb60Doris Liu 2351a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin entry.contentLoader.startLoad(); 2361a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin return entry.contentLoader.isRequestInProgress(); 237f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 238f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 239f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private void cancelNonactiveImages() { 240f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int range = Math.max( 241f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin (mContentEnd - mActiveEnd), (mActiveStart - mContentStart)); 242f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (int i = 0 ;i < range; ++i) { 2431a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin cancelSlotImage(mActiveEnd + i); 2441a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin cancelSlotImage(mActiveStart - 1 - i); 245f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 246f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 247f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 2481a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin private void cancelSlotImage(int slotIndex) { 249f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (slotIndex < mContentStart || slotIndex >= mContentEnd) return; 2501a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin AlbumEntry item = mData[slotIndex % mData.length]; 2511a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin if (item.contentLoader != null) item.contentLoader.cancelLoad(); 252f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 253f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 254f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private void freeSlotContent(int slotIndex) { 2551a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin AlbumEntry data[] = mData; 256f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int index = slotIndex % data.length; 2571a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin AlbumEntry entry = data[index]; 2583535d67239b1b1e4ee038f39dece64545b78f2edOwen Lin if (entry.contentLoader != null) entry.contentLoader.recycle(); 2593535d67239b1b1e4ee038f39dece64545b78f2edOwen Lin if (entry.bitmapTexture != null) entry.bitmapTexture.recycle(); 2601a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin data[index] = null; 261f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 262f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 2631a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin private void prepareSlotContent(int slotIndex) { 2641a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin AlbumEntry entry = new AlbumEntry(); 2651a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin MediaItem item = mSource.get(slotIndex); // item could be null; 2661a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin entry.item = item; 2671a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin entry.mediaType = (item == null) 2681a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin ? MediaItem.MEDIA_TYPE_UNKNOWN 2691a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin : entry.item.getMediaType(); 2701a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin entry.path = (item == null) ? null : item.getPath(); 2711a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin entry.rotation = (item == null) ? 0 : item.getRotation(); 2721a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin entry.contentLoader = new ThumbnailLoader(slotIndex, entry.item); 2731a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin mData[slotIndex % mData.length] = entry; 274f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 275f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 276f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private void updateAllImageRequests() { 277f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mActiveRequestCount = 0; 278f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (int i = mActiveStart, n = mActiveEnd; i < n; ++i) { 2791a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin if (requestSlotImage(i)) ++mActiveRequestCount; 280f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 281f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mActiveRequestCount == 0) { 282f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin requestNonactiveImages(); 283f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } else { 284f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin cancelNonactiveImages(); 285f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 286f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 287f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 2881a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin private class ThumbnailLoader extends BitmapLoader { 289d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin private final int mSlotIndex; 290d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin private final MediaItem mItem; 2911a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin 2921a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin public ThumbnailLoader(int slotIndex, MediaItem item) { 293f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mSlotIndex = slotIndex; 2941a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin mItem = item; 295f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 296f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 297f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 2981a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin protected Future<Bitmap> submitBitmapTask(FutureListener<Bitmap> l) { 2991a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin return mThreadPool.submit( 3001a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin mItem.requestImage(MediaItem.TYPE_MICROTHUMBNAIL), this); 301f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 302f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 303f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 3041a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin protected void onLoadComplete(Bitmap bitmap) { 3051a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin mHandler.obtainMessage(MSG_UPDATE_ENTRY, this).sendToTarget(); 306f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 307f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 3081a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin public void updateEntry() { 309d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin Bitmap bitmap = getBitmap(); 310d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin if (bitmap == null) return; // error or recycled 3111a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin AlbumEntry entry = mData[mSlotIndex % mData.length]; 312adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin entry.bitmapTexture = new TiledTexture(bitmap); 3133535d67239b1b1e4ee038f39dece64545b78f2edOwen Lin entry.content = entry.bitmapTexture; 314f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 3151a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin if (isActiveSlot(mSlotIndex)) { 316adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin mTileUploader.addTexture(entry.bitmapTexture); 3171a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin --mActiveRequestCount; 3181a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin if (mActiveRequestCount == 0) requestNonactiveImages(); 3191a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin if (mListener != null) mListener.onContentChanged(); 320d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin } else { 321adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin mTileUploader.addTexture(entry.bitmapTexture); 3221a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin } 323f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 324f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 325f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 3261a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin @Override 327f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void onSizeChanged(int size) { 328f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mSize != size) { 329f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mSize = size; 330f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mListener != null) mListener.onSizeChanged(mSize); 331cd938f3f05975de73658dc2f2b6c632b7ee569a3Yuli Huang if (mContentEnd > mSize) mContentEnd = mSize; 332cd938f3f05975de73658dc2f2b6c632b7ee569a3Yuli Huang if (mActiveEnd > mSize) mActiveEnd = mSize; 333f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 334f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 335f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 3361a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin @Override 337c3d8ac3b9504346dafc49e006b5f732dd1db21e8Owen Lin public void onContentChanged(int index) { 338f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (index >= mContentStart && index < mContentEnd && mIsActive) { 339c3d8ac3b9504346dafc49e006b5f732dd1db21e8Owen Lin freeSlotContent(index); 340c3d8ac3b9504346dafc49e006b5f732dd1db21e8Owen Lin prepareSlotContent(index); 341c3d8ac3b9504346dafc49e006b5f732dd1db21e8Owen Lin updateAllImageRequests(); 342c3d8ac3b9504346dafc49e006b5f732dd1db21e8Owen Lin if (mListener != null && isActiveSlot(index)) { 343c3d8ac3b9504346dafc49e006b5f732dd1db21e8Owen Lin mListener.onContentChanged(); 344c3d8ac3b9504346dafc49e006b5f732dd1db21e8Owen Lin } 345f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 346f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 347f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 348f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void resume() { 349f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mIsActive = true; 350adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin TiledTexture.prepareResources(); 351f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (int i = mContentStart, n = mContentEnd; i < n; ++i) { 352f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin prepareSlotContent(i); 353f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 354f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin updateAllImageRequests(); 355f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 356f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 357f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void pause() { 358f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mIsActive = false; 359adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin mTileUploader.clear(); 360adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin TiledTexture.freeResources(); 361f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (int i = mContentStart, n = mContentEnd; i < n; ++i) { 362f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin freeSlotContent(i); 363f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 364f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 365f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin} 366