MediaFeed.java revision 053a906072e581a9bd381003ceefdf14636a7c1d
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();
217f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            // We also need to delete the items from the cluster.
218f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            MediaClustering clustering = mClusterSets.get(set);
219f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            for (int j = 0; j < numItems; ++j) {
220f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                MediaItem item = items.get(j);
221f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                removeItemFromMediaSet(item, set);
222f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                if (clustering != null) {
223f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                    clustering.removeItemFromClustering(item);
224f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                }
225f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            }
226f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            set.updateNumExpectedItems();
227f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            set.generateTitle(true);
228f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        }
229f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    }
230f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    updateListener(true);
231d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks                    mMediaFeedNeedsToRun = true;
232f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    if (mDataSource != null) {
233f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        mDataSource.performOperation(OPERATION_DELETE, mediaBuckets, null);
234f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    }
235f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                } else {
236f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    mDataSource.performOperation(operation, mediaBuckets, data);
237f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                }
238f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            }
239f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        });
240f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        operationThread.setName("Operation " + operation);
241f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        operationThread.start();
242f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
243f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
244f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public void removeMediaSet(MediaSet set) {
2452b04f591f758b7af03c43d90e91b939cbd515506Venkat Krishnaraj        synchronized (mMediaSets) {
2462b04f591f758b7af03c43d90e91b939cbd515506Venkat Krishnaraj        	mMediaSets.remove(set);
2472b04f591f758b7af03c43d90e91b939cbd515506Venkat Krishnaraj        }
248d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks        mMediaFeedNeedsToRun = true;
249f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
250f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
251f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    private void removeItemFromMediaSet(MediaItem item, MediaSet mediaSet) {
252f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        mediaSet.removeItem(item);
253d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks        synchronized (mClusterSets) {
254f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            MediaClustering clustering = mClusterSets.get(mediaSet);
255f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            if (clustering != null) {
256f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                clustering.removeItemFromClustering(item);
257f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            }
258f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
259d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks        mMediaFeedNeedsToRun = true;
260f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
261f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
262f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public void updateListener(boolean needsLayout) {
263f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        mListenerNeedsUpdate = true;
264f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        mListenerNeedsLayout = needsLayout;
265f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
266f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
267f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public int getNumSlots() {
268f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        int currentMediaSetIndex = mExpandedMediaSetIndex;
269f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        ArrayList<MediaSet> mediaSets = mMediaSets;
270f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        int mediaSetsSize = mediaSets.size();
271f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
272f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        if (mInClusteringMode == false) {
273f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            if (currentMediaSetIndex == Shared.INVALID || currentMediaSetIndex >= mediaSetsSize) {
274f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                return mediaSetsSize;
275f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            } else {
276f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                MediaSet setToUse = (mMediaFilteredSet == null) ? mediaSets.get(currentMediaSetIndex) : mMediaFilteredSet;
277f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                return setToUse.getNumItems();
278f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            }
279f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        } else if (currentMediaSetIndex != Shared.INVALID && currentMediaSetIndex < mediaSetsSize) {
280f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            MediaSet set = mediaSets.get(currentMediaSetIndex);
281f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            MediaClustering clustering = mClusterSets.get(set);
282f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            if (clustering != null) {
283f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                return clustering.getClustersForDisplay().size();
284f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            }
285f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
286f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        return 0;
287f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
288f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
289f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public MediaSet getSetForSlot(int slotIndex) {
290f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        if (slotIndex < 0) {
291f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            return null;
292f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
293f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
294f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        ArrayList<MediaSet> mediaSets = mMediaSets;
295f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        int mediaSetsSize = mediaSets.size();
296f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        int currentMediaSetIndex = mExpandedMediaSetIndex;
297f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
298f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        if (mInClusteringMode == false) {
299f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            if (currentMediaSetIndex == Shared.INVALID || currentMediaSetIndex >= mediaSetsSize) {
300f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                if (slotIndex >= mediaSetsSize) {
301f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    return null;
302f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                }
303f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                return mMediaSets.get(slotIndex);
304f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            }
305f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            if (mSingleWrapper.getNumItems() == 0) {
306f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                mSingleWrapper.addItem(null);
307f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            }
308f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            MediaSet setToUse = (mMediaFilteredSet == null) ? mMediaSets.get(currentMediaSetIndex) : mMediaFilteredSet;
309f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            ArrayList<MediaItem> items = setToUse.getItems();
310f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            if (slotIndex >= setToUse.getNumItems()) {
311f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                return null;
312f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            }
313f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            mSingleWrapper.getItems().set(0, items.get(slotIndex));
314f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            return mSingleWrapper;
315f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        } else if (currentMediaSetIndex != Shared.INVALID && currentMediaSetIndex < mediaSetsSize) {
316f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            MediaSet set = mediaSets.get(currentMediaSetIndex);
317f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            MediaClustering clustering = mClusterSets.get(set);
318f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            if (clustering != null) {
319f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                ArrayList<MediaClustering.Cluster> clusters = clustering.getClustersForDisplay();
320f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                if (clusters.size() > slotIndex) {
321f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    MediaClustering.Cluster cluster = clusters.get(slotIndex);
322f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    cluster.generateCaption(mContext);
323f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    return cluster;
324f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                }
325f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            }
326f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
327f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        return null;
328f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
329f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
330f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public boolean getWaitingForMediaScanner() {
331f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        return mWaitingForMediaScanner;
332f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
333d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks
334f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public boolean isLoading() {
335f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        return mLoading;
336f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
337f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
338f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public void start() {
339f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        final MediaFeed feed = this;
340f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        mLoading = true;
341d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks        mDataSourceThread = new Thread(this);
342d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks        mDataSourceThread.setName("MediaFeed");
343f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        mAlbumSourceThread = new Thread(new Runnable() {
344f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            public void run() {
345f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                if (mContext == null)
346f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    return;
347f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
348f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                DataSource dataSource = mDataSource;
349f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                // We must wait while the SD card is mounted or the MediaScanner is running.
350d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks                if (dataSource != null) {
351d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks                    dataSource.loadMediaSets(feed);
352d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks                }
353f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                mWaitingForMediaScanner = false;
354f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                while (ImageManager.isMediaScannerScanning(mContext.getContentResolver())) {
355f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    // MediaScanner is still running, wait
356f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    mWaitingForMediaScanner = true;
357f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    try {
358f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        if (mContext == null)
359f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            return;
360f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        showToast(mContext.getResources().getString(R.string.initializing), Toast.LENGTH_LONG);
361f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        Thread.sleep(6000);
362f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    } catch (InterruptedException e) {
363f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
364f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    }
365f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                }
366f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                if (mWaitingForMediaScanner) {
367f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    showToast(mContext.getResources().getString(R.string.loading_new), Toast.LENGTH_LONG);
368d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks                    mWaitingForMediaScanner = false;
369d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks                    if (dataSource != null) {
370d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks                        dataSource.loadMediaSets(feed);
371d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks                    }
372f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                }
373f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                mLoading = false;
374f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            }
375f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        });
376f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        mAlbumSourceThread.setName("MediaSets");
377f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        mAlbumSourceThread.start();
378f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
379f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
380f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    private void showToast(final String string, final int duration) {
381f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        showToast(string, duration, false);
382f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
383f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
384f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    private void showToast(final String string, final int duration, final boolean centered) {
385d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks        if (mContext != null && !((Gallery) mContext).isPaused()) {
386f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            ((Gallery) mContext).getHandler().post(new Runnable() {
387f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                public void run() {
388f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    if (mContext != null) {
389f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        Toast toast = Toast.makeText(mContext, string, duration);
390f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        if (centered) {
391f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            toast.setGravity(Gravity.CENTER, 0, 0);
392f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        }
393f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        toast.show();
394f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    }
395f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                }
396f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            });
397f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
398f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
399f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
400f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public void run() {
401f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        DataSource dataSource = mDataSource;
402d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks        int sleepMs = 10;
403f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
404f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        if (dataSource != null) {
405d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks            while (!Thread.interrupted()) {
406f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                if (mListenerNeedsUpdate) {
407f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    mListenerNeedsUpdate = false;
408f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    if (mListener != null)
409f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        mListener.onFeedChanged(this, mListenerNeedsLayout);
410f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    try {
411f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        Thread.sleep(sleepMs);
412f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    } catch (InterruptedException e) {
413f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        return;
414f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    }
415f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                } else {
416d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks                    if (mWaitingForMediaScanner) {
417d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks                        synchronized (mMediaSets) {
418d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks                            mMediaSets.clear();
419d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks                        }
420d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks                    }
421f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    try {
422f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        Thread.sleep(sleepMs);
423f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    } catch (InterruptedException e) {
424f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        return;
425f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    }
426f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                }
427d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks                sleepMs = 300;
428d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks                if (!mMediaFeedNeedsToRun)
429d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks                    continue;
430d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks                mMediaFeedNeedsToRun = false;
431f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                ArrayList<MediaSet> mediaSets = mMediaSets;
432f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                synchronized (mediaSets) {
433f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    int expandedSetIndex = mExpandedMediaSetIndex;
434f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    if (expandedSetIndex >= mMediaSets.size()) {
435f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        expandedSetIndex = Shared.INVALID;
436f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    }
437f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    if (expandedSetIndex == Shared.INVALID) {
438f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        // We purge the sets outside this visibleRange.
4392b04f591f758b7af03c43d90e91b939cbd515506Venkat Krishnaraj                        int numSets = mediaSets.size();
440f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        IndexRange visibleRange = mVisibleRange;
441f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        IndexRange bufferedRange = mBufferedRange;
442f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        boolean scanMediaSets = true;
443f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        for (int i = 0; i < numSets; ++i) {
444f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            if (i >= visibleRange.begin && i <= visibleRange.end && scanMediaSets) {
445f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                MediaSet set = mediaSets.get(i);
446f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                int numItemsLoaded = set.mNumItemsLoaded;
447f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                if (numItemsLoaded < set.getNumExpectedItems() && numItemsLoaded < 8) {
448f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                    dataSource.loadItemsForSet(this, set, numItemsLoaded, 8);
449f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                    if (set.getNumExpectedItems() == 0) {
450f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                        mediaSets.remove(set);
451f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                        break;
452f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                    }
453f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                    if (mListener != null) {
454f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                        mListener.onFeedChanged(this, false);
455f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                    }
456f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                    sleepMs = 100;
457f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                    scanMediaSets = false;
458f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                }
459d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks                                if (!set.setContainsValidItems()) {
460d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks                                    mediaSets.remove(set);
461d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks                                    if (mListener != null) {
462d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks                                        mListener.onFeedChanged(this, false);
463d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks                                    }
464d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks                                    break;
465d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks                                }
466f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            }
467f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        }
4682b04f591f758b7af03c43d90e91b939cbd515506Venkat Krishnaraj                        numSets = mediaSets.size();
469f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        for (int i = 0; i < numSets; ++i) {
470f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            MediaSet set = mediaSets.get(i);
471f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            if (i >= bufferedRange.begin && i <= bufferedRange.end) {
472f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                if (scanMediaSets) {
473f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                    int numItemsLoaded = set.mNumItemsLoaded;
474f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                    if (numItemsLoaded < set.getNumExpectedItems() && numItemsLoaded < 8) {
475f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                        dataSource.loadItemsForSet(this, set, numItemsLoaded, 8);
476f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                        if (set.getNumExpectedItems() == 0) {
477f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                            mediaSets.remove(set);
478f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                            break;
479f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                        }
480f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                        if (mListener != null) {
481f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                            mListener.onFeedChanged(this, false);
482f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                        }
483f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                        sleepMs = 100;
484f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                        scanMediaSets = false;
485f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                    }
486f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                }
487d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks                            } else if (i < bufferedRange.begin || i > bufferedRange.end) {
488f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                // Purge this set to its initial status.
489f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                MediaClustering clustering = mClusterSets.get(set);
490f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                if (clustering != null) {
491f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                    clustering.clear();
492f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                    mClusterSets.remove(set);
493f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                }
494f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                if (set.getNumItems() != 0)
495f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                    set.clear();
496f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            }
497f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        }
498f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    }
499f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    if (expandedSetIndex != Shared.INVALID) {
500f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        int numSets = mMediaSets.size();
501f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        for (int i = 0; i < numSets; ++i) {
502f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            // Purge other sets.
503f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            if (i != expandedSetIndex) {
504f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                MediaSet set = mediaSets.get(i);
505f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                MediaClustering clustering = mClusterSets.get(set);
506f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                if (clustering != null) {
507f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                    clustering.clear();
508f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                    mClusterSets.remove(set);
509f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                }
510f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                if (set.getNumItems() != 0)
511f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                    set.clear();
512f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            }
513f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        }
514f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        // Make sure all the items are loaded for the album.
515f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        int numItemsLoaded = mediaSets.get(expandedSetIndex).mNumItemsLoaded;
516f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        int requestedItems = mVisibleRange.end;
517f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        // requestedItems count changes in clustering mode.
518f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        if (mInClusteringMode && mClusterSets != null) {
519f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            requestedItems = 0;
520f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            MediaClustering clustering = mClusterSets.get(mediaSets.get(expandedSetIndex));
521db87908d640e17ef0946824be158d86c6e2d6836Dave Sparks                            if (clustering != null) {
522db87908d640e17ef0946824be158d86c6e2d6836Dave Sparks                                ArrayList<Cluster> clusters = clustering.getClustersForDisplay();
523db87908d640e17ef0946824be158d86c6e2d6836Dave Sparks                                int numClusters = clusters.size();
524db87908d640e17ef0946824be158d86c6e2d6836Dave Sparks                                for (int i = 0; i < numClusters; i++) {
525db87908d640e17ef0946824be158d86c6e2d6836Dave Sparks                                    requestedItems += clusters.get(i).getNumExpectedItems();
526db87908d640e17ef0946824be158d86c6e2d6836Dave Sparks                                }
527f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            }
528f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        }
529f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        MediaSet set = mediaSets.get(expandedSetIndex);
530f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        if (numItemsLoaded < set.getNumExpectedItems()) {
531f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            // TODO(Venkat) Why are we doing 4th param calculations like this?
532f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            dataSource.loadItemsForSet(this, set, numItemsLoaded, (requestedItems / NUM_ITEMS_LOOKAHEAD)
533f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                    * NUM_ITEMS_LOOKAHEAD + NUM_ITEMS_LOOKAHEAD);
534f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            if (set.getNumExpectedItems() == 0) {
535f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                mediaSets.remove(set);
536f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                mListener.onFeedChanged(this, false);
537f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            }
538f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            if (numItemsLoaded != set.mNumItemsLoaded && mListener != null) {
539f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                mListener.onFeedChanged(this, false);
540f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            }
541f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        }
542f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    }
543f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    MediaFilter filter = mMediaFilter;
544f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    if (filter != null && mMediaFilteredSet == null) {
545f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        if (expandedSetIndex != Shared.INVALID) {
546f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            MediaSet set = mediaSets.get(expandedSetIndex);
547f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            ArrayList<MediaItem> items = set.getItems();
548f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            int numItems = set.getNumItems();
549f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            MediaSet filteredSet = new MediaSet();
550f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            filteredSet.setNumExpectedItems(numItems);
551f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            mMediaFilteredSet = filteredSet;
552f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            for (int i = 0; i < numItems; ++i) {
553f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                MediaItem item = items.get(i);
554f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                if (filter.pass(item)) {
555f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                    filteredSet.addItem(item);
556f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                                }
557f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            }
558f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            filteredSet.updateNumExpectedItems();
559f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                            filteredSet.generateTitle(true);
560f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        }
561f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                        updateListener(true);
562f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    }
563f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                }
564f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            }
565f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
566f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
567f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
568f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public void expandMediaSet(int mediaSetIndex) {
569f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        // We need to check if this slot can be focused or not.
570f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        if (mListener != null) {
571f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            mListener.onFeedAboutToChange(this);
572f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
573f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        if (mExpandedMediaSetIndex > 0 && mediaSetIndex == Shared.INVALID) {
574f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            // We are collapsing a previously expanded media set
575f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            if (mediaSetIndex < mMediaSets.size() && mExpandedMediaSetIndex >= 0) {
576f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                MediaSet set = mMediaSets.get(mExpandedMediaSetIndex);
577f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                if (set.getNumItems() == 0) {
578f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    set.clear();
579f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                }
580f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            }
581f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
582f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        mExpandedMediaSetIndex = mediaSetIndex;
583f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        if (mediaSetIndex < mMediaSets.size() && mediaSetIndex >= 0) {
584f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            // Notify Picasa that the user entered the album.
585f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            // MediaSet set = mMediaSets.get(mediaSetIndex);
586f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            // PicasaService.requestSync(mContext, PicasaService.TYPE_ALBUM_PHOTOS, set.mPicasaAlbumId);
587f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
588f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        updateListener(true);
589d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks        mMediaFeedNeedsToRun = true;
590f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
591f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
592f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public boolean canExpandSet(int slotIndex) {
593f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        int mediaSetIndex = slotIndex;
594f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        if (mediaSetIndex < mMediaSets.size() && mediaSetIndex >= 0) {
595f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            MediaSet set = mMediaSets.get(mediaSetIndex);
596f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            if (set.getNumItems() > 0) {
597f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                MediaItem item = set.getItems().get(0);
598f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                if (item.mId == Shared.INVALID) {
599f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    return false;
600f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                }
601f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                return true;
602f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            }
603f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
604f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        return false;
605f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
606f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
607f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public boolean hasExpandedMediaSet() {
608f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        return (mExpandedMediaSetIndex != Shared.INVALID);
609f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
610f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
611f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public boolean restorePreviousClusteringState() {
612f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        boolean retVal = disableClusteringIfNecessary();
613f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        if (retVal) {
614f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            if (mListener != null) {
615f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                mListener.onFeedAboutToChange(this);
616f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            }
617f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            updateListener(true);
618d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks            mMediaFeedNeedsToRun = true;
619f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
620f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        return retVal;
621f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
622f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
623f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    private boolean disableClusteringIfNecessary() {
624f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        if (mInClusteringMode) {
625f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            // Disable clustering.
626f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            mInClusteringMode = false;
627d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks            mMediaFeedNeedsToRun = true;
628f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            return true;
629f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
630f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        return false;
631f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
632f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
633f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public boolean isClustered() {
634f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        return mInClusteringMode;
635f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
636f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
637f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public MediaSet getCurrentSet() {
638f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        if (mExpandedMediaSetIndex != Shared.INVALID && mExpandedMediaSetIndex < mMediaSets.size()) {
639f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            return mMediaSets.get(mExpandedMediaSetIndex);
640f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
641f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        return null;
642f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
643f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
644f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public void performClustering() {
645f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        if (mListener != null) {
646f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            mListener.onFeedAboutToChange(this);
647f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
648f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        MediaSet setToUse = null;
649f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        if (mExpandedMediaSetIndex != Shared.INVALID || mExpandedMediaSetIndex < mMediaSets.size()) {
650f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            setToUse = mMediaSets.get(mExpandedMediaSetIndex);
651f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
652f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        if (setToUse != null) {
653f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            MediaClustering clustering = null;
654d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks            synchronized (mClusterSets) {
655f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                // Make sure the computation is completed to the end.
656f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                clustering = mClusterSets.get(setToUse);
657f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                if (clustering != null) {
658f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    clustering.compute(null, true);
659f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                } else {
660f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                    return;
661f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                }
662f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            }
663f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            mInClusteringMode = true;
664d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks            mMediaFeedNeedsToRun = true;
665f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            updateListener(true);
666f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
667f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
668f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
669f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public void moveSetToFront(MediaSet mediaSet) {
670f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        ArrayList<MediaSet> mediaSets = mMediaSets;
671f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        int numSets = mediaSets.size();
672f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        if (numSets == 0) {
673f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            mediaSets.add(mediaSet);
674f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            return;
675f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
676f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        MediaSet setToFind = mediaSets.get(0);
677f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        if (setToFind == mediaSet) {
678f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            return;
679f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
680f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        mediaSets.set(0, mediaSet);
681f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        int indexToSwapTill = -1;
682f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        for (int i = 1; i < numSets; ++i) {
683f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            MediaSet set = mediaSets.get(i);
684f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            if (set == mediaSet) {
685f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                mediaSets.set(i, setToFind);
686f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                indexToSwapTill = i;
687f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                break;
688f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            }
689f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
690f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        if (indexToSwapTill != Shared.INVALID) {
691f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            for (int i = indexToSwapTill; i > 1; --i) {
692f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                MediaSet setEnd = mediaSets.get(i);
693f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                MediaSet setPrev = mediaSets.get(i - 1);
694f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                mediaSets.set(i, setPrev);
695f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                mediaSets.set(i - 1, setEnd);
696f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            }
697f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
698d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks        mMediaFeedNeedsToRun = true;
699f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
700f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
701f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public MediaSet replaceMediaSet(long setId, DataSource dataSource) {
702f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        MediaSet mediaSet = new MediaSet(dataSource);
703f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        mediaSet.mId = setId;
704f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        ArrayList<MediaSet> mediaSets = mMediaSets;
705f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        int numSets = mediaSets.size();
706f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        for (int i = 0; i < numSets; ++i) {
707053a906072e581a9bd381003ceefdf14636a7c1dVenkat Krishnaraj        	final MediaSet thisSet = mediaSets.get(i);
708053a906072e581a9bd381003ceefdf14636a7c1dVenkat Krishnaraj            if (thisSet.mId == setId) {
709f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                mediaSet.mName = thisSet.mName;
710053a906072e581a9bd381003ceefdf14636a7c1dVenkat Krishnaraj                mediaSet.mHasImages = thisSet.mHasImages;
711053a906072e581a9bd381003ceefdf14636a7c1dVenkat Krishnaraj                mediaSet.mHasVideos = thisSet.mHasVideos;
712f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                mediaSets.set(i, mediaSet);
713f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks                break;
714f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            }
715f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        }
716d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks        mMediaFeedNeedsToRun = true;
717f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        return mediaSet;
718f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
719d8a6d17db8aaef2ea06c78fe643f06601d8aec5dDave Sparks
720f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public void setSingleImageMode(boolean singleImageMode) {
721f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        mSingleImageMode = singleImageMode;
722f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
723f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
724f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public boolean isSingleImageMode() {
725f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        return mSingleImageMode;
726f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
727f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks
728f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    public MediaSet getExpandedMediaSet() {
729f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        if (mExpandedMediaSetIndex == Shared.INVALID)
730f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            return null;
731f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        if (mExpandedMediaSetIndex >= mMediaSets.size())
732f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks            return null;
733f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks        return mMediaSets.get(mExpandedMediaSetIndex);
734f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks    }
735f99dfe8549fb6c2c06c8cb7ca7d5eb33002c809eDave Sparks}
736