MediaFeed.java revision 88ed7e72a2a0bfdbef7f72aea2b2ddfd74961bdb
1f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparkspackage com.cooliris.media; 2f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks 3f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparksimport java.util.ArrayList; 4f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparksimport java.util.HashMap; 5f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks 6f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparksimport android.content.Context; 7f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparksimport android.view.Gravity; 8f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparksimport android.widget.Toast; 9f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparksimport android.os.Process; 10f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks 11f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparksimport com.cooliris.media.MediaClustering.Cluster; 12f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks 13f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparkspublic final class MediaFeed implements Runnable { 14f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks public static final int OPERATION_DELETE = 0; 15f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks public static final int OPERATION_ROTATE = 1; 16f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks public static final int OPERATION_CROP = 2; 17f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks 18f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks private static final int NUM_ITEMS_LOOKAHEAD = 60; 19f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks 20f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks private IndexRange mVisibleRange = new IndexRange(); 21f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks private IndexRange mBufferedRange = new IndexRange(); 22f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks private ArrayList<MediaSet> mMediaSets = new ArrayList<MediaSet>(); 23f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks private Listener mListener; 24f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks private DataSource mDataSource; 25f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks private boolean mListenerNeedsUpdate = false; 26d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks private boolean mMediaFeedNeedsToRun = false; 27f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks private MediaSet mSingleWrapper = new MediaSet(); 28f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks private boolean mInClusteringMode = false; 29f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks private HashMap<MediaSet, MediaClustering> mClusterSets = new HashMap<MediaSet, MediaClustering>(32); 30f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks private int mExpandedMediaSetIndex = Shared.INVALID; 31f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks private MediaFilter mMediaFilter; 32f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks private MediaSet mMediaFilteredSet; 33f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks private Context mContext; 34f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks private Thread mDataSourceThread = null; 35f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks private Thread mAlbumSourceThread = null; 36f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks private boolean mListenerNeedsLayout; 37f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks private boolean mWaitingForMediaScanner; 38f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks private boolean mSingleImageMode; 39f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks private boolean mLoading; 40f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks 41f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks public interface Listener { 42f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks public abstract void onFeedAboutToChange(MediaFeed feed); 43f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks 44f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks public abstract void onFeedChanged(MediaFeed feed, boolean needsLayout); 45f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 46f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks 47f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks public MediaFeed(Context context, DataSource dataSource, Listener listener) { 48f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mContext = context; 49f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mListener = listener; 50f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mDataSource = dataSource; 51f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mSingleWrapper.setNumExpectedItems(1); 52f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mLoading = true; 53f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 54d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks 55f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks public void shutdown() { 56f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (mDataSourceThread != null) { 57f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mDataSource.shutdown(); 58f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mDataSourceThread.interrupt(); 59f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mDataSourceThread = null; 60f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 61f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (mAlbumSourceThread != null) { 62f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mAlbumSourceThread.interrupt(); 63f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mAlbumSourceThread = null; 64f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 65f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks int numSets = mMediaSets.size(); 66f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks for (int i = 0; i < numSets; ++i) { 67f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks MediaSet set = mMediaSets.get(i); 68f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks set.clear(); 69f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 70f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks synchronized (mMediaSets) { 71f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mMediaSets.clear(); 72f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 73f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks int numClusters = mClusterSets.size(); 74f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks for (int i = 0; i < numClusters; ++i) { 75f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks MediaClustering mc = mClusterSets.get(i); 76f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (mc != null) { 77f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mc.clear(); 78f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 79f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 80f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mClusterSets.clear(); 81f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mListener = null; 82f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mDataSource = null; 83f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mSingleWrapper = null; 84f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 85f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks 86f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks public void setVisibleRange(int begin, int end) { 87d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks if (begin != mVisibleRange.begin || end != mVisibleRange.end) { 88d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks mVisibleRange.begin = begin; 89d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks mVisibleRange.end = end; 90d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks int numItems = 96; 91d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks int numItemsBy2 = numItems / 2; 92d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks int numItemsBy4 = numItems / 4; 93d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks mBufferedRange.begin = (begin / numItemsBy2) * numItemsBy2 - numItemsBy4; 94d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks mBufferedRange.end = mBufferedRange.begin + numItems; 95d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks mMediaFeedNeedsToRun = true; 96d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks } 97f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 98f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks 99f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks public void setFilter(MediaFilter filter) { 100f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mMediaFilter = filter; 101f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mMediaFilteredSet = null; 102f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (mListener != null) { 103f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mListener.onFeedAboutToChange(this); 104f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 105d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks mMediaFeedNeedsToRun = true; 106f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 107f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks 108f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks public void removeFilter() { 109f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mMediaFilter = null; 110f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mMediaFilteredSet = null; 111f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (mListener != null) { 112f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mListener.onFeedAboutToChange(this); 113f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks updateListener(true); 114f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 115d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks mMediaFeedNeedsToRun = true; 116f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 117f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks 118f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks public ArrayList<MediaSet> getMediaSets() { 119f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks return mMediaSets; 120f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 121f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks 122d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks public MediaSet getMediaSet(final long setId) { 123f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (setId != Shared.INVALID) { 124d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks try { 125d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks int mMediaSetsSize = mMediaSets.size(); 126d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks for (int i = 0; i < mMediaSetsSize; i++) { 127d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks if (mMediaSets.get(i).mId == setId) { 128d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks return mMediaSets.get(i); 129d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks } 130f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 131d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks } catch (Exception e) { 132d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks return null; 133f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 134f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 135f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks return null; 136f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 137f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks 138f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks public MediaSet getFilteredSet() { 139f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks return mMediaFilteredSet; 140f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 141f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks 142f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks public MediaSet addMediaSet(final long setId, DataSource dataSource) { 143f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks MediaSet mediaSet = new MediaSet(dataSource); 144f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mediaSet.mId = setId; 145f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mMediaSets.add(mediaSet); 146d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks if (mDataSourceThread != null && !mDataSourceThread.isAlive()) { 147d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks mDataSourceThread.start(); 148d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks } 149d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks mMediaFeedNeedsToRun = true; 150f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks return mediaSet; 151f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 152f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks 153f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks public DataSource getDataSource() { 154f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks return mDataSource; 155f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 156f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks 157f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks public MediaClustering getClustering() { 158f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (mExpandedMediaSetIndex != Shared.INVALID && mExpandedMediaSetIndex < mMediaSets.size()) { 159f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks return mClusterSets.get(mMediaSets.get(mExpandedMediaSetIndex)); 160f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 161f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks return null; 162f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 163f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks 164f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks public ArrayList<Cluster> getClustersForSet(final MediaSet set) { 165f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks ArrayList<Cluster> clusters = null; 166f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (mClusterSets != null && mClusterSets.containsKey(set)) { 167f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks MediaClustering mediaClustering = mClusterSets.get(set); 168f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (mediaClustering != null) { 169f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks clusters = mediaClustering.getClusters(); 170f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 171f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 172f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks return clusters; 173f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 174f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks 175f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks public void addItemToMediaSet(MediaItem item, MediaSet mediaSet) { 176f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks item.mParentMediaSet = mediaSet; 177f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mediaSet.addItem(item); 178d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks synchronized (mClusterSets) { 179f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (item.mClusteringState == MediaItem.NOT_CLUSTERED) { 180f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks MediaClustering clustering = mClusterSets.get(mediaSet); 181f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (clustering == null) { 182f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks clustering = new MediaClustering(mediaSet.isPicassaAlbum()); 183f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mClusterSets.put(mediaSet, clustering); 184f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 185f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks clustering.setTimeRange(mediaSet.mMaxTimestamp - mediaSet.mMinTimestamp, mediaSet.getNumExpectedItems()); 186f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks clustering.addItemForClustering(item); 187f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks item.mClusteringState = MediaItem.CLUSTERED; 188f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 189f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 190d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks mMediaFeedNeedsToRun = true; 191f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 192f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks 193f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks public void performOperation(final int operation, final ArrayList<MediaBucket> mediaBuckets, final Object data) { 194f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks int numBuckets = mediaBuckets.size(); 195f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks final ArrayList<MediaBucket> copyMediaBuckets = new ArrayList<MediaBucket>(numBuckets); 196f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks for (int i = 0; i < numBuckets; ++i) { 197f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks copyMediaBuckets.add(mediaBuckets.get(i)); 198f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 199f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (operation == OPERATION_DELETE && mListener != null) { 200f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mListener.onFeedAboutToChange(this); 201f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 202f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks Thread operationThread = new Thread(new Runnable() { 203f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks public void run() { 204f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks ArrayList<MediaBucket> mediaBuckets = copyMediaBuckets; 205f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (operation == OPERATION_DELETE) { 206f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks int numBuckets = mediaBuckets.size(); 207f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks for (int i = 0; i < numBuckets; ++i) { 208f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks MediaBucket bucket = mediaBuckets.get(i); 209f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks MediaSet set = bucket.mediaSet; 210f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks ArrayList<MediaItem> items = bucket.mediaItems; 211f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (set != null && items == null) { 212f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks // Remove the entire bucket. 213f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks removeMediaSet(set); 214f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } else if (set != null && items != null) { 215f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks // We need to remove these items from the set. 216f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks int numItems = items.size(); 2171bb0c42b2a62f580eea4764d6a4434ffecfbf353Dave Sparks // We also need to delete the items from the 2181bb0c42b2a62f580eea4764d6a4434ffecfbf353Dave Sparks // cluster. 219f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks MediaClustering clustering = mClusterSets.get(set); 220f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks for (int j = 0; j < numItems; ++j) { 221f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks MediaItem item = items.get(j); 222f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks removeItemFromMediaSet(item, set); 223f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (clustering != null) { 224f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks clustering.removeItemFromClustering(item); 225f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 226f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 227f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks set.updateNumExpectedItems(); 228f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks set.generateTitle(true); 229f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 230f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 231f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks updateListener(true); 232d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks mMediaFeedNeedsToRun = true; 233f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (mDataSource != null) { 234f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mDataSource.performOperation(OPERATION_DELETE, mediaBuckets, null); 235f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 236f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } else { 237f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mDataSource.performOperation(operation, mediaBuckets, data); 238f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 239f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 240f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks }); 241f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks operationThread.setName("Operation " + operation); 242f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks operationThread.start(); 243f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 244f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks 245f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks public void removeMediaSet(MediaSet set) { 2462b04f591f758b7af03c43d90e91b939cbd515506Venkat Krishnaraj synchronized (mMediaSets) { 2471bb0c42b2a62f580eea4764d6a4434ffecfbf353Dave Sparks mMediaSets.remove(set); 2482b04f591f758b7af03c43d90e91b939cbd515506Venkat Krishnaraj } 249d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks mMediaFeedNeedsToRun = true; 250f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 251f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks 252f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks private void removeItemFromMediaSet(MediaItem item, MediaSet mediaSet) { 253f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mediaSet.removeItem(item); 254d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks synchronized (mClusterSets) { 255f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks MediaClustering clustering = mClusterSets.get(mediaSet); 256f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (clustering != null) { 257f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks clustering.removeItemFromClustering(item); 258f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 259f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 260d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks mMediaFeedNeedsToRun = true; 261f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 262f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks 263f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks public void updateListener(boolean needsLayout) { 264f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mListenerNeedsUpdate = true; 265f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mListenerNeedsLayout = needsLayout; 266f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 267f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks 268f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks public int getNumSlots() { 269f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks int currentMediaSetIndex = mExpandedMediaSetIndex; 270f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks ArrayList<MediaSet> mediaSets = mMediaSets; 271f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks int mediaSetsSize = mediaSets.size(); 272f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks 273f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (mInClusteringMode == false) { 274f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (currentMediaSetIndex == Shared.INVALID || currentMediaSetIndex >= mediaSetsSize) { 275f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks return mediaSetsSize; 276f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } else { 277f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks MediaSet setToUse = (mMediaFilteredSet == null) ? mediaSets.get(currentMediaSetIndex) : mMediaFilteredSet; 278f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks return setToUse.getNumItems(); 279f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 280f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } else if (currentMediaSetIndex != Shared.INVALID && currentMediaSetIndex < mediaSetsSize) { 281f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks MediaSet set = mediaSets.get(currentMediaSetIndex); 282f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks MediaClustering clustering = mClusterSets.get(set); 283f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (clustering != null) { 284f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks return clustering.getClustersForDisplay().size(); 285f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 286f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 287f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks return 0; 288f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 289f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks 290f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks public MediaSet getSetForSlot(int slotIndex) { 291f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (slotIndex < 0) { 292f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks return null; 293f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 294f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks 295f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks ArrayList<MediaSet> mediaSets = mMediaSets; 296f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks int mediaSetsSize = mediaSets.size(); 297f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks int currentMediaSetIndex = mExpandedMediaSetIndex; 298f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks 299f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (mInClusteringMode == false) { 300f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (currentMediaSetIndex == Shared.INVALID || currentMediaSetIndex >= mediaSetsSize) { 301f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (slotIndex >= mediaSetsSize) { 302f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks return null; 303f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 304f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks return mMediaSets.get(slotIndex); 305f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 306f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (mSingleWrapper.getNumItems() == 0) { 307f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mSingleWrapper.addItem(null); 308f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 309f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks MediaSet setToUse = (mMediaFilteredSet == null) ? mMediaSets.get(currentMediaSetIndex) : mMediaFilteredSet; 310f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks ArrayList<MediaItem> items = setToUse.getItems(); 311f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (slotIndex >= setToUse.getNumItems()) { 312f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks return null; 313f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 314f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mSingleWrapper.getItems().set(0, items.get(slotIndex)); 315f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks return mSingleWrapper; 316f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } else if (currentMediaSetIndex != Shared.INVALID && currentMediaSetIndex < mediaSetsSize) { 317f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks MediaSet set = mediaSets.get(currentMediaSetIndex); 318f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks MediaClustering clustering = mClusterSets.get(set); 319f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (clustering != null) { 320f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks ArrayList<MediaClustering.Cluster> clusters = clustering.getClustersForDisplay(); 321f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (clusters.size() > slotIndex) { 322f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks MediaClustering.Cluster cluster = clusters.get(slotIndex); 323f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks cluster.generateCaption(mContext); 324f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks return cluster; 325f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 326f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 327f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 328f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks return null; 329f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 330f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks 331f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks public boolean getWaitingForMediaScanner() { 332f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks return mWaitingForMediaScanner; 333f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 334d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks 335f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks public boolean isLoading() { 336f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks return mLoading; 337f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 338f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks 339f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks public void start() { 340f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks final MediaFeed feed = this; 341f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mLoading = true; 342d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks mDataSourceThread = new Thread(this); 343d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks mDataSourceThread.setName("MediaFeed"); 344f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mAlbumSourceThread = new Thread(new Runnable() { 345f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks public void run() { 346f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (mContext == null) 347f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks return; 348f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); 349f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks DataSource dataSource = mDataSource; 3501bb0c42b2a62f580eea4764d6a4434ffecfbf353Dave Sparks // We must wait while the SD card is mounted or the MediaScanner 3511bb0c42b2a62f580eea4764d6a4434ffecfbf353Dave Sparks // is running. 352d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks if (dataSource != null) { 353d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks dataSource.loadMediaSets(feed); 354d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks } 355f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mWaitingForMediaScanner = false; 356f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks while (ImageManager.isMediaScannerScanning(mContext.getContentResolver())) { 357f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks // MediaScanner is still running, wait 35888ed7e72a2a0bfdbef7f72aea2b2ddfd74961bdbVenkat Krishnaraj if (Thread.interrupted()) 35988ed7e72a2a0bfdbef7f72aea2b2ddfd74961bdbVenkat Krishnaraj return; 360f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mWaitingForMediaScanner = true; 361f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks try { 362f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (mContext == null) 363f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks return; 364f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks showToast(mContext.getResources().getString(R.string.initializing), Toast.LENGTH_LONG); 365f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks Thread.sleep(6000); 366f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } catch (InterruptedException e) { 36788ed7e72a2a0bfdbef7f72aea2b2ddfd74961bdbVenkat Krishnaraj return; 368f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 369f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 370f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (mWaitingForMediaScanner) { 371f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks showToast(mContext.getResources().getString(R.string.loading_new), Toast.LENGTH_LONG); 372d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks mWaitingForMediaScanner = false; 373d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks if (dataSource != null) { 374d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks dataSource.loadMediaSets(feed); 375d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks } 376f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 377f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mLoading = false; 378f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 379f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks }); 380f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mAlbumSourceThread.setName("MediaSets"); 381f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mAlbumSourceThread.start(); 382f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 383f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks 384f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks private void showToast(final String string, final int duration) { 385f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks showToast(string, duration, false); 386f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 387f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks 388f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks private void showToast(final String string, final int duration, final boolean centered) { 389d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks if (mContext != null && !((Gallery) mContext).isPaused()) { 390f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks ((Gallery) mContext).getHandler().post(new Runnable() { 391f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks public void run() { 392f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (mContext != null) { 393f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks Toast toast = Toast.makeText(mContext, string, duration); 394f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (centered) { 395f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks toast.setGravity(Gravity.CENTER, 0, 0); 396f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 397f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks toast.show(); 398f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 399f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 400f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks }); 401f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 402f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 403f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks 404f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks public void run() { 405f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks DataSource dataSource = mDataSource; 406d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks int sleepMs = 10; 407f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); 408f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (dataSource != null) { 409d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks while (!Thread.interrupted()) { 410f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (mListenerNeedsUpdate) { 411f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mListenerNeedsUpdate = false; 412f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (mListener != null) 413f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mListener.onFeedChanged(this, mListenerNeedsLayout); 414f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks try { 415f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks Thread.sleep(sleepMs); 416f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } catch (InterruptedException e) { 417f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks return; 418f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 419f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } else { 420d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks if (mWaitingForMediaScanner) { 421d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks synchronized (mMediaSets) { 422d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks mMediaSets.clear(); 423d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks } 424d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks } 425f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks try { 426f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks Thread.sleep(sleepMs); 427f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } catch (InterruptedException e) { 428f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks return; 429f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 430f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 431d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks sleepMs = 300; 432d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks if (!mMediaFeedNeedsToRun) 433d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks continue; 434d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks mMediaFeedNeedsToRun = false; 435f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks ArrayList<MediaSet> mediaSets = mMediaSets; 436f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks synchronized (mediaSets) { 437f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks int expandedSetIndex = mExpandedMediaSetIndex; 438f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (expandedSetIndex >= mMediaSets.size()) { 439f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks expandedSetIndex = Shared.INVALID; 440f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 441f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (expandedSetIndex == Shared.INVALID) { 442f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks // We purge the sets outside this visibleRange. 4432b04f591f758b7af03c43d90e91b939cbd515506Venkat Krishnaraj int numSets = mediaSets.size(); 444f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks IndexRange visibleRange = mVisibleRange; 445f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks IndexRange bufferedRange = mBufferedRange; 446f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks boolean scanMediaSets = true; 447f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks for (int i = 0; i < numSets; ++i) { 448f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (i >= visibleRange.begin && i <= visibleRange.end && scanMediaSets) { 449f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks MediaSet set = mediaSets.get(i); 450f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks int numItemsLoaded = set.mNumItemsLoaded; 451f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (numItemsLoaded < set.getNumExpectedItems() && numItemsLoaded < 8) { 452f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks dataSource.loadItemsForSet(this, set, numItemsLoaded, 8); 453f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (set.getNumExpectedItems() == 0) { 454f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mediaSets.remove(set); 455f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks break; 456f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 457f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (mListener != null) { 458f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mListener.onFeedChanged(this, false); 459f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 460f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks sleepMs = 100; 461f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks scanMediaSets = false; 462f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 463d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks if (!set.setContainsValidItems()) { 464d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks mediaSets.remove(set); 465d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks if (mListener != null) { 466d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks mListener.onFeedChanged(this, false); 467d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks } 468d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks break; 469d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks } 470f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 471f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 4722b04f591f758b7af03c43d90e91b939cbd515506Venkat Krishnaraj numSets = mediaSets.size(); 473f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks for (int i = 0; i < numSets; ++i) { 474f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks MediaSet set = mediaSets.get(i); 475f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (i >= bufferedRange.begin && i <= bufferedRange.end) { 476f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (scanMediaSets) { 477f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks int numItemsLoaded = set.mNumItemsLoaded; 478f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (numItemsLoaded < set.getNumExpectedItems() && numItemsLoaded < 8) { 479f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks dataSource.loadItemsForSet(this, set, numItemsLoaded, 8); 480f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (set.getNumExpectedItems() == 0) { 481f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mediaSets.remove(set); 482f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks break; 483f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 484f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (mListener != null) { 485f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mListener.onFeedChanged(this, false); 486f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 487f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks sleepMs = 100; 488f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks scanMediaSets = false; 489f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 490f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 491d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks } else if (i < bufferedRange.begin || i > bufferedRange.end) { 492f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks // Purge this set to its initial status. 493f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks MediaClustering clustering = mClusterSets.get(set); 494f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (clustering != null) { 495f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks clustering.clear(); 496f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mClusterSets.remove(set); 497f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 498f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (set.getNumItems() != 0) 499f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks set.clear(); 500f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 501f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 502f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 503f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (expandedSetIndex != Shared.INVALID) { 504f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks int numSets = mMediaSets.size(); 505f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks for (int i = 0; i < numSets; ++i) { 506f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks // Purge other sets. 507f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (i != expandedSetIndex) { 508f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks MediaSet set = mediaSets.get(i); 509f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks MediaClustering clustering = mClusterSets.get(set); 510f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (clustering != null) { 511f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks clustering.clear(); 512f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mClusterSets.remove(set); 513f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 514f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (set.getNumItems() != 0) 515f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks set.clear(); 516f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 517f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 518f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks // Make sure all the items are loaded for the album. 519f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks int numItemsLoaded = mediaSets.get(expandedSetIndex).mNumItemsLoaded; 520f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks int requestedItems = mVisibleRange.end; 521f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks // requestedItems count changes in clustering mode. 522f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (mInClusteringMode && mClusterSets != null) { 523f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks requestedItems = 0; 524f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks MediaClustering clustering = mClusterSets.get(mediaSets.get(expandedSetIndex)); 525db87908d640e17ef0946824be158d86c6e2d6836Dave Sparks if (clustering != null) { 526db87908d640e17ef0946824be158d86c6e2d6836Dave Sparks ArrayList<Cluster> clusters = clustering.getClustersForDisplay(); 527db87908d640e17ef0946824be158d86c6e2d6836Dave Sparks int numClusters = clusters.size(); 528db87908d640e17ef0946824be158d86c6e2d6836Dave Sparks for (int i = 0; i < numClusters; i++) { 529db87908d640e17ef0946824be158d86c6e2d6836Dave Sparks requestedItems += clusters.get(i).getNumExpectedItems(); 530db87908d640e17ef0946824be158d86c6e2d6836Dave Sparks } 531f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 532f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 533f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks MediaSet set = mediaSets.get(expandedSetIndex); 534f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (numItemsLoaded < set.getNumExpectedItems()) { 5351bb0c42b2a62f580eea4764d6a4434ffecfbf353Dave Sparks // We perform calculations for a window that gets anchored to a multiple of NUM_ITEMS_LOOKAHEAD. 5361bb0c42b2a62f580eea4764d6a4434ffecfbf353Dave Sparks // The start of the window is 0, x, 2x, 3x ... etc where x = NUM_ITEMS_LOOKAHEAD. 537f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks dataSource.loadItemsForSet(this, set, numItemsLoaded, (requestedItems / NUM_ITEMS_LOOKAHEAD) 538f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks * NUM_ITEMS_LOOKAHEAD + NUM_ITEMS_LOOKAHEAD); 539f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (set.getNumExpectedItems() == 0) { 540f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mediaSets.remove(set); 541f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mListener.onFeedChanged(this, false); 542f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 543f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (numItemsLoaded != set.mNumItemsLoaded && mListener != null) { 544f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mListener.onFeedChanged(this, false); 545f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 546f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 547f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 548f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks MediaFilter filter = mMediaFilter; 549f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (filter != null && mMediaFilteredSet == null) { 550f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (expandedSetIndex != Shared.INVALID) { 551f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks MediaSet set = mediaSets.get(expandedSetIndex); 552f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks ArrayList<MediaItem> items = set.getItems(); 553f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks int numItems = set.getNumItems(); 554f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks MediaSet filteredSet = new MediaSet(); 555f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks filteredSet.setNumExpectedItems(numItems); 556f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mMediaFilteredSet = filteredSet; 557f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks for (int i = 0; i < numItems; ++i) { 558f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks MediaItem item = items.get(i); 559f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (filter.pass(item)) { 560f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks filteredSet.addItem(item); 561f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 562f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 563f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks filteredSet.updateNumExpectedItems(); 564f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks filteredSet.generateTitle(true); 565f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 566f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks updateListener(true); 567f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 568f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 569f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 570f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 571f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 572f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks 573f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks public void expandMediaSet(int mediaSetIndex) { 574f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks // We need to check if this slot can be focused or not. 575f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (mListener != null) { 576f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mListener.onFeedAboutToChange(this); 577f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 578f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (mExpandedMediaSetIndex > 0 && mediaSetIndex == Shared.INVALID) { 579f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks // We are collapsing a previously expanded media set 5801bb0c42b2a62f580eea4764d6a4434ffecfbf353Dave Sparks if (mediaSetIndex < mMediaSets.size() && mExpandedMediaSetIndex >= 0 && mExpandedMediaSetIndex < mMediaSets.size()) { 581f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks MediaSet set = mMediaSets.get(mExpandedMediaSetIndex); 582f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (set.getNumItems() == 0) { 583f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks set.clear(); 584f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 585f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 586f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 587f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mExpandedMediaSetIndex = mediaSetIndex; 588f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (mediaSetIndex < mMediaSets.size() && mediaSetIndex >= 0) { 589f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks // Notify Picasa that the user entered the album. 590f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks // MediaSet set = mMediaSets.get(mediaSetIndex); 5911bb0c42b2a62f580eea4764d6a4434ffecfbf353Dave Sparks // PicasaService.requestSync(mContext, 5921bb0c42b2a62f580eea4764d6a4434ffecfbf353Dave Sparks // PicasaService.TYPE_ALBUM_PHOTOS, set.mPicasaAlbumId); 593f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 594f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks updateListener(true); 595d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks mMediaFeedNeedsToRun = true; 596f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 597f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks 598f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks public boolean canExpandSet(int slotIndex) { 599f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks int mediaSetIndex = slotIndex; 600f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (mediaSetIndex < mMediaSets.size() && mediaSetIndex >= 0) { 601f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks MediaSet set = mMediaSets.get(mediaSetIndex); 602f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (set.getNumItems() > 0) { 603f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks MediaItem item = set.getItems().get(0); 604f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (item.mId == Shared.INVALID) { 605f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks return false; 606f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 607f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks return true; 608f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 609f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 610f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks return false; 611f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 612f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks 613f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks public boolean hasExpandedMediaSet() { 614f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks return (mExpandedMediaSetIndex != Shared.INVALID); 615f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 616f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks 617f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks public boolean restorePreviousClusteringState() { 618f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks boolean retVal = disableClusteringIfNecessary(); 619f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (retVal) { 620f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (mListener != null) { 621f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mListener.onFeedAboutToChange(this); 622f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 623f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks updateListener(true); 624d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks mMediaFeedNeedsToRun = true; 625f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 626f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks return retVal; 627f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 628f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks 629f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks private boolean disableClusteringIfNecessary() { 630f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (mInClusteringMode) { 631f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks // Disable clustering. 632f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mInClusteringMode = false; 633d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks mMediaFeedNeedsToRun = true; 634f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks return true; 635f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 636f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks return false; 637f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 638f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks 639f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks public boolean isClustered() { 640f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks return mInClusteringMode; 641f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 642f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks 643f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks public MediaSet getCurrentSet() { 644f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (mExpandedMediaSetIndex != Shared.INVALID && mExpandedMediaSetIndex < mMediaSets.size()) { 645f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks return mMediaSets.get(mExpandedMediaSetIndex); 646f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 647f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks return null; 648f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 649f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks 650f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks public void performClustering() { 651f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (mListener != null) { 652f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mListener.onFeedAboutToChange(this); 653f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 654f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks MediaSet setToUse = null; 655f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (mExpandedMediaSetIndex != Shared.INVALID || mExpandedMediaSetIndex < mMediaSets.size()) { 656f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks setToUse = mMediaSets.get(mExpandedMediaSetIndex); 657f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 658f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (setToUse != null) { 659f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks MediaClustering clustering = null; 660d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks synchronized (mClusterSets) { 661f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks // Make sure the computation is completed to the end. 662f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks clustering = mClusterSets.get(setToUse); 663f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (clustering != null) { 664f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks clustering.compute(null, true); 665f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } else { 666f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks return; 667f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 668f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 669f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mInClusteringMode = true; 670d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks mMediaFeedNeedsToRun = true; 671f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks updateListener(true); 672f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 673f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 674f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks 675f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks public void moveSetToFront(MediaSet mediaSet) { 676f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks ArrayList<MediaSet> mediaSets = mMediaSets; 677f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks int numSets = mediaSets.size(); 678f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (numSets == 0) { 679f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mediaSets.add(mediaSet); 680f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks return; 681f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 682f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks MediaSet setToFind = mediaSets.get(0); 683f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (setToFind == mediaSet) { 684f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks return; 685f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 686f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mediaSets.set(0, mediaSet); 687f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks int indexToSwapTill = -1; 688f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks for (int i = 1; i < numSets; ++i) { 689f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks MediaSet set = mediaSets.get(i); 690f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (set == mediaSet) { 691f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mediaSets.set(i, setToFind); 692f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks indexToSwapTill = i; 693f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks break; 694f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 695f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 696f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (indexToSwapTill != Shared.INVALID) { 697f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks for (int i = indexToSwapTill; i > 1; --i) { 698f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks MediaSet setEnd = mediaSets.get(i); 699f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks MediaSet setPrev = mediaSets.get(i - 1); 700f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mediaSets.set(i, setPrev); 701f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mediaSets.set(i - 1, setEnd); 702f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 703f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 704d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks mMediaFeedNeedsToRun = true; 705f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 706f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks 707f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks public MediaSet replaceMediaSet(long setId, DataSource dataSource) { 708f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks MediaSet mediaSet = new MediaSet(dataSource); 709f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mediaSet.mId = setId; 710f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks ArrayList<MediaSet> mediaSets = mMediaSets; 711f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks int numSets = mediaSets.size(); 712f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks for (int i = 0; i < numSets; ++i) { 7131bb0c42b2a62f580eea4764d6a4434ffecfbf353Dave Sparks final MediaSet thisSet = mediaSets.get(i); 714053a906072e581a9bd381003ceefdf14636a7c1dVenkat Krishnaraj if (thisSet.mId == setId) { 715f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mediaSet.mName = thisSet.mName; 716053a906072e581a9bd381003ceefdf14636a7c1dVenkat Krishnaraj mediaSet.mHasImages = thisSet.mHasImages; 717053a906072e581a9bd381003ceefdf14636a7c1dVenkat Krishnaraj mediaSet.mHasVideos = thisSet.mHasVideos; 718f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mediaSets.set(i, mediaSet); 719f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks break; 720f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 721f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 722d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks mMediaFeedNeedsToRun = true; 723f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks return mediaSet; 724f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 725d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks 726f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks public void setSingleImageMode(boolean singleImageMode) { 727f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks mSingleImageMode = singleImageMode; 728f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 729f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks 730f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks public boolean isSingleImageMode() { 731f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks return mSingleImageMode; 732f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 733f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks 734f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks public MediaSet getExpandedMediaSet() { 735f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (mExpandedMediaSetIndex == Shared.INVALID) 736f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks return null; 737f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks if (mExpandedMediaSetIndex >= mMediaSets.size()) 738f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks return null; 739f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks return mMediaSets.get(mExpandedMediaSetIndex); 740f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks } 741f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks} 742