--- /dev/null
+package com.cooliris.media;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import android.content.Context;
+import android.view.Gravity;
+import android.widget.Toast;
+import android.os.Process;
+
+import com.cooliris.media.MediaClustering.Cluster;
+
+public final class MediaFeed implements Runnable {
+ public static final int OPERATION_DELETE = 0;
+ public static final int OPERATION_ROTATE = 1;
+ public static final int OPERATION_CROP = 2;
+
+ private static final int NUM_ITEMS_LOOKAHEAD = 60;
+
+ private IndexRange mVisibleRange = new IndexRange();
+ private IndexRange mBufferedRange = new IndexRange();
+ private ArrayList<MediaSet> mMediaSets = new ArrayList<MediaSet>();
+ private Listener mListener;
+ private DataSource mDataSource;
+ private boolean mListenerNeedsUpdate = false;
+ private boolean mMediaFeedNeedsToRun = false;
+ private MediaSet mSingleWrapper = new MediaSet();
+ private boolean mInClusteringMode = false;
+ private HashMap<MediaSet, MediaClustering> mClusterSets = new HashMap<MediaSet, MediaClustering>(32);
+ private int mExpandedMediaSetIndex = Shared.INVALID;
+ private MediaFilter mMediaFilter;
+ private MediaSet mMediaFilteredSet;
+ private Context mContext;
+ private Thread mDataSourceThread = null;
+ private Thread mAlbumSourceThread = null;
+ private boolean mListenerNeedsLayout;
+ private boolean mWaitingForMediaScanner;
+ private boolean mSingleImageMode;
+ private boolean mLoading;
+
+ public interface Listener {
+ public abstract void onFeedAboutToChange(MediaFeed feed);
+
+ public abstract void onFeedChanged(MediaFeed feed, boolean needsLayout);
+ }
+
+ public MediaFeed(Context context, DataSource dataSource, Listener listener) {
+ mContext = context;
+ mListener = listener;
+ mDataSource = dataSource;
+ mSingleWrapper.setNumExpectedItems(1);
+ mLoading = true;
+ }
+
+ public void shutdown() {
+ if (mDataSourceThread != null) {
+ mDataSource.shutdown();
+ mDataSourceThread.interrupt();
+ mDataSourceThread = null;
+ }
+ if (mAlbumSourceThread != null) {
+ mAlbumSourceThread.interrupt();
+ mAlbumSourceThread = null;
+ }
+ int numSets = mMediaSets.size();
+ for (int i = 0; i < numSets; ++i) {
+ MediaSet set = mMediaSets.get(i);
+ set.clear();
+ }
+ synchronized (mMediaSets) {
+ mMediaSets.clear();
+ }
+ int numClusters = mClusterSets.size();
+ for (int i = 0; i < numClusters; ++i) {
+ MediaClustering mc = mClusterSets.get(i);
+ if (mc != null) {
+ mc.clear();
+ }
+ }
+ mClusterSets.clear();
+ mListener = null;
+ mDataSource = null;
+ mSingleWrapper = null;
+ }
+
+ public void setVisibleRange(int begin, int end) {
+ if (begin != mVisibleRange.begin || end != mVisibleRange.end) {
+ mVisibleRange.begin = begin;
+ mVisibleRange.end = end;
+ int numItems = 96;
+ int numItemsBy2 = numItems / 2;
+ int numItemsBy4 = numItems / 4;
+ mBufferedRange.begin = (begin / numItemsBy2) * numItemsBy2 - numItemsBy4;
+ mBufferedRange.end = mBufferedRange.begin + numItems;
+ mMediaFeedNeedsToRun = true;
+ }
+ }
+
+ public void setFilter(MediaFilter filter) {
+ mMediaFilter = filter;
+ mMediaFilteredSet = null;
+ if (mListener != null) {
+ mListener.onFeedAboutToChange(this);
+ }
+ mMediaFeedNeedsToRun = true;
+ }
+
+ public void removeFilter() {
+ mMediaFilter = null;
+ mMediaFilteredSet = null;
+ if (mListener != null) {
+ mListener.onFeedAboutToChange(this);
+ updateListener(true);
+ }
+ mMediaFeedNeedsToRun = true;
+ }
+
+ public ArrayList<MediaSet> getMediaSets() {
+ return mMediaSets;
+ }
+
+ public MediaSet getMediaSet(final long setId) {
+ if (setId != Shared.INVALID) {
+ try {
+ int mMediaSetsSize = mMediaSets.size();
+ for (int i = 0; i < mMediaSetsSize; i++) {
+ if (mMediaSets.get(i).mId == setId) {
+ return mMediaSets.get(i);
+ }
+ }
+ } catch (Exception e) {
+ return null;
+ }
+ }
+ return null;
+ }
+
+ public MediaSet getFilteredSet() {
+ return mMediaFilteredSet;
+ }
+
+ public MediaSet addMediaSet(final long setId, DataSource dataSource) {
+ MediaSet mediaSet = new MediaSet(dataSource);
+ mediaSet.mId = setId;
+ mMediaSets.add(mediaSet);
+ if (mDataSourceThread != null && !mDataSourceThread.isAlive()) {
+ mDataSourceThread.start();
+ }
+ mMediaFeedNeedsToRun = true;
+ return mediaSet;
+ }
+
+ public DataSource getDataSource() {
+ return mDataSource;
+ }
+
+ public MediaClustering getClustering() {
+ if (mExpandedMediaSetIndex != Shared.INVALID && mExpandedMediaSetIndex < mMediaSets.size()) {
+ return mClusterSets.get(mMediaSets.get(mExpandedMediaSetIndex));
+ }
+ return null;
+ }
+
+ public ArrayList<Cluster> getClustersForSet(final MediaSet set) {
+ ArrayList<Cluster> clusters = null;
+ if (mClusterSets != null && mClusterSets.containsKey(set)) {
+ MediaClustering mediaClustering = mClusterSets.get(set);
+ if (mediaClustering != null) {
+ clusters = mediaClustering.getClusters();
+ }
+ }
+ return clusters;
+ }
+
+ public void addItemToMediaSet(MediaItem item, MediaSet mediaSet) {
+ item.mParentMediaSet = mediaSet;
+ mediaSet.addItem(item);
+ synchronized (mClusterSets) {
+ if (item.mClusteringState == MediaItem.NOT_CLUSTERED) {
+ MediaClustering clustering = mClusterSets.get(mediaSet);
+ if (clustering == null) {
+ clustering = new MediaClustering(mediaSet.isPicassaAlbum());
+ mClusterSets.put(mediaSet, clustering);
+ }
+ clustering.setTimeRange(mediaSet.mMaxTimestamp - mediaSet.mMinTimestamp, mediaSet.getNumExpectedItems());
+ clustering.addItemForClustering(item);
+ item.mClusteringState = MediaItem.CLUSTERED;
+ }
+ }
+ mMediaFeedNeedsToRun = true;
+ }
+
+ public void performOperation(final int operation, final ArrayList<MediaBucket> mediaBuckets, final Object data) {
+ int numBuckets = mediaBuckets.size();
+ final ArrayList<MediaBucket> copyMediaBuckets = new ArrayList<MediaBucket>(numBuckets);
+ for (int i = 0; i < numBuckets; ++i) {
+ copyMediaBuckets.add(mediaBuckets.get(i));
+ }
+ if (operation == OPERATION_DELETE && mListener != null) {
+ mListener.onFeedAboutToChange(this);
+ }
+ Thread operationThread = new Thread(new Runnable() {
+ public void run() {
+ ArrayList<MediaBucket> mediaBuckets = copyMediaBuckets;
+ if (operation == OPERATION_DELETE) {
+ int numBuckets = mediaBuckets.size();
+ for (int i = 0; i < numBuckets; ++i) {
+ MediaBucket bucket = mediaBuckets.get(i);
+ MediaSet set = bucket.mediaSet;
+ ArrayList<MediaItem> items = bucket.mediaItems;
+ if (set != null && items == null) {
+ // Remove the entire bucket.
+ removeMediaSet(set);
+ } else if (set != null && items != null) {
+ // We need to remove these items from the set.
+ int numItems = items.size();
+ // We also need to delete the items from the
+ // cluster.
+ MediaClustering clustering = mClusterSets.get(set);
+ for (int j = 0; j < numItems; ++j) {
+ MediaItem item = items.get(j);
+ removeItemFromMediaSet(item, set);
+ if (clustering != null) {
+ clustering.removeItemFromClustering(item);
+ }
+ }
+ set.updateNumExpectedItems();
+ set.generateTitle(true);
+ }
+ }
+ updateListener(true);
+ mMediaFeedNeedsToRun = true;
+ if (mDataSource != null) {
+ mDataSource.performOperation(OPERATION_DELETE, mediaBuckets, null);
+ }
+ } else {
+ mDataSource.performOperation(operation, mediaBuckets, data);
+ }
+ }
+ });
+ operationThread.setName("Operation " + operation);
+ operationThread.start();
+ }
+
+ public void removeMediaSet(MediaSet set) {
+ synchronized (mMediaSets) {
+ mMediaSets.remove(set);
+ }
+ mMediaFeedNeedsToRun = true;
+ }
+
+ private void removeItemFromMediaSet(MediaItem item, MediaSet mediaSet) {
+ mediaSet.removeItem(item);
+ synchronized (mClusterSets) {
+ MediaClustering clustering = mClusterSets.get(mediaSet);
+ if (clustering != null) {
+ clustering.removeItemFromClustering(item);
+ }
+ }
+ mMediaFeedNeedsToRun = true;
+ }
+
+ public void updateListener(boolean needsLayout) {
+ mListenerNeedsUpdate = true;
+ mListenerNeedsLayout = needsLayout;
+ }
+
+ public int getNumSlots() {
+ int currentMediaSetIndex = mExpandedMediaSetIndex;
+ ArrayList<MediaSet> mediaSets = mMediaSets;
+ int mediaSetsSize = mediaSets.size();
+
+ if (mInClusteringMode == false) {
+ if (currentMediaSetIndex == Shared.INVALID || currentMediaSetIndex >= mediaSetsSize) {
+ return mediaSetsSize;
+ } else {
+ MediaSet setToUse = (mMediaFilteredSet == null) ? mediaSets.get(currentMediaSetIndex) : mMediaFilteredSet;
+ return setToUse.getNumItems();
+ }
+ } else if (currentMediaSetIndex != Shared.INVALID && currentMediaSetIndex < mediaSetsSize) {
+ MediaSet set = mediaSets.get(currentMediaSetIndex);
+ MediaClustering clustering = mClusterSets.get(set);
+ if (clustering != null) {
+ return clustering.getClustersForDisplay().size();
+ }
+ }
+ return 0;
+ }
+
+ public MediaSet getSetForSlot(int slotIndex) {
+ if (slotIndex < 0) {
+ return null;
+ }
+
+ ArrayList<MediaSet> mediaSets = mMediaSets;
+ int mediaSetsSize = mediaSets.size();
+ int currentMediaSetIndex = mExpandedMediaSetIndex;
+
+ if (mInClusteringMode == false) {
+ if (currentMediaSetIndex == Shared.INVALID || currentMediaSetIndex >= mediaSetsSize) {
+ if (slotIndex >= mediaSetsSize) {
+ return null;
+ }
+ return mMediaSets.get(slotIndex);
+ }
+ if (mSingleWrapper.getNumItems() == 0) {
+ mSingleWrapper.addItem(null);
+ }
+ MediaSet setToUse = (mMediaFilteredSet == null) ? mMediaSets.get(currentMediaSetIndex) : mMediaFilteredSet;
+ ArrayList<MediaItem> items = setToUse.getItems();
+ if (slotIndex >= setToUse.getNumItems()) {
+ return null;
+ }
+ mSingleWrapper.getItems().set(0, items.get(slotIndex));
+ return mSingleWrapper;
+ } else if (currentMediaSetIndex != Shared.INVALID && currentMediaSetIndex < mediaSetsSize) {
+ MediaSet set = mediaSets.get(currentMediaSetIndex);
+ MediaClustering clustering = mClusterSets.get(set);
+ if (clustering != null) {
+ ArrayList<MediaClustering.Cluster> clusters = clustering.getClustersForDisplay();
+ if (clusters.size() > slotIndex) {
+ MediaClustering.Cluster cluster = clusters.get(slotIndex);
+ cluster.generateCaption(mContext);
+ return cluster;
+ }
+ }
+ }
+ return null;
+ }
+
+ public boolean getWaitingForMediaScanner() {
+ return mWaitingForMediaScanner;
+ }
+
+ public boolean isLoading() {
+ return mLoading;
+ }
+
+ public void start() {
+ final MediaFeed feed = this;
+ mLoading = true;
+ mDataSourceThread = new Thread(this);
+ mDataSourceThread.setName("MediaFeed");
+ mAlbumSourceThread = new Thread(new Runnable() {
+ public void run() {
+ if (mContext == null)
+ return;
+ Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
+ DataSource dataSource = mDataSource;
+ // We must wait while the SD card is mounted or the MediaScanner
+ // is running.
+ if (dataSource != null) {
+ dataSource.loadMediaSets(feed);
+ }
+ mWaitingForMediaScanner = false;
+ while (ImageManager.isMediaScannerScanning(mContext.getContentResolver())) {
+ // MediaScanner is still running, wait
+ if (Thread.interrupted())
+ return;
+ mWaitingForMediaScanner = true;
+ try {
+ if (mContext == null)
+ return;
+ showToast(mContext.getResources().getString(R.string.initializing), Toast.LENGTH_LONG);
+ Thread.sleep(6000);
+ } catch (InterruptedException e) {
+ return;
+ }
+ }
+ if (mWaitingForMediaScanner) {
+ showToast(mContext.getResources().getString(R.string.loading_new), Toast.LENGTH_LONG);
+ mWaitingForMediaScanner = false;
+ if (dataSource != null) {
+ dataSource.loadMediaSets(feed);
+ }
+ }
+ mLoading = false;
+ }
+ });
+ mAlbumSourceThread.setName("MediaSets");
+ mAlbumSourceThread.start();
+ }
+
+ private void showToast(final String string, final int duration) {
+ showToast(string, duration, false);
+ }
+
+ private void showToast(final String string, final int duration, final boolean centered) {
+ if (mContext != null && !((Gallery) mContext).isPaused()) {
+ ((Gallery) mContext).getHandler().post(new Runnable() {
+ public void run() {
+ if (mContext != null) {
+ Toast toast = Toast.makeText(mContext, string, duration);
+ if (centered) {
+ toast.setGravity(Gravity.CENTER, 0, 0);
+ }
+ toast.show();
+ }
+ }
+ });
+ }
+ }
+
+ public void run() {
+ DataSource dataSource = mDataSource;
+ int sleepMs = 10;
+ Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
+ if (dataSource != null) {
+ while (!Thread.interrupted()) {
+ if (mListenerNeedsUpdate) {
+ mListenerNeedsUpdate = false;
+ if (mListener != null)
+ mListener.onFeedChanged(this, mListenerNeedsLayout);
+ try {
+ Thread.sleep(sleepMs);
+ } catch (InterruptedException e) {
+ return;
+ }
+ } else {
+ if (mWaitingForMediaScanner) {
+ synchronized (mMediaSets) {
+ mMediaSets.clear();
+ }
+ }
+ try {
+ Thread.sleep(sleepMs);
+ } catch (InterruptedException e) {
+ return;
+ }
+ }
+ sleepMs = 300;
+ if (!mMediaFeedNeedsToRun)
+ continue;
+ if (((Gallery) mContext).isPaused())
+ continue;
+ mMediaFeedNeedsToRun = false;
+ ArrayList<MediaSet> mediaSets = mMediaSets;
+ synchronized (mediaSets) {
+ int expandedSetIndex = mExpandedMediaSetIndex;
+ if (expandedSetIndex >= mMediaSets.size()) {
+ expandedSetIndex = Shared.INVALID;
+ }
+ if (expandedSetIndex == Shared.INVALID) {
+ // We purge the sets outside this visibleRange.
+ int numSets = mediaSets.size();
+ IndexRange visibleRange = mVisibleRange;
+ IndexRange bufferedRange = mBufferedRange;
+ boolean scanMediaSets = true;
+ for (int i = 0; i < numSets; ++i) {
+ if (i >= visibleRange.begin && i <= visibleRange.end && scanMediaSets) {
+ MediaSet set = mediaSets.get(i);
+ int numItemsLoaded = set.mNumItemsLoaded;
+ if (numItemsLoaded < set.getNumExpectedItems() && numItemsLoaded < 8) {
+ dataSource.loadItemsForSet(this, set, numItemsLoaded, 8);
+ if (set.getNumExpectedItems() == 0) {
+ mediaSets.remove(set);
+ break;
+ }
+ if (mListener != null) {
+ mListener.onFeedChanged(this, false);
+ }
+ sleepMs = 100;
+ scanMediaSets = false;
+ }
+ if (!set.setContainsValidItems()) {
+ mediaSets.remove(set);
+ if (mListener != null) {
+ mListener.onFeedChanged(this, false);
+ }
+ break;
+ }
+ }
+ }
+ numSets = mediaSets.size();
+ for (int i = 0; i < numSets; ++i) {
+ MediaSet set = mediaSets.get(i);
+ if (i >= bufferedRange.begin && i <= bufferedRange.end) {
+ if (scanMediaSets) {
+ int numItemsLoaded = set.mNumItemsLoaded;
+ if (numItemsLoaded < set.getNumExpectedItems() && numItemsLoaded < 8) {
+ dataSource.loadItemsForSet(this, set, numItemsLoaded, 8);
+ if (set.getNumExpectedItems() == 0) {
+ mediaSets.remove(set);
+ break;
+ }
+ if (mListener != null) {
+ mListener.onFeedChanged(this, false);
+ }
+ sleepMs = 100;
+ scanMediaSets = false;
+ }
+ }
+ } else if (i < bufferedRange.begin || i > bufferedRange.end) {
+ // Purge this set to its initial status.
+ MediaClustering clustering = mClusterSets.get(set);
+ if (clustering != null) {
+ clustering.clear();
+ mClusterSets.remove(set);
+ }
+ if (set.getNumItems() != 0)
+ set.clear();
+ }
+ }
+ }
+ if (expandedSetIndex != Shared.INVALID) {
+ int numSets = mMediaSets.size();
+ for (int i = 0; i < numSets; ++i) {
+ // Purge other sets.
+ if (i != expandedSetIndex) {
+ MediaSet set = mediaSets.get(i);
+ MediaClustering clustering = mClusterSets.get(set);
+ if (clustering != null) {
+ clustering.clear();
+ mClusterSets.remove(set);
+ }
+ if (set.getNumItems() != 0)
+ set.clear();
+ }
+ }
+ // Make sure all the items are loaded for the album.
+ int numItemsLoaded = mediaSets.get(expandedSetIndex).mNumItemsLoaded;
+ int requestedItems = mVisibleRange.end;
+ // requestedItems count changes in clustering mode.
+ if (mInClusteringMode && mClusterSets != null) {
+ requestedItems = 0;
+ MediaClustering clustering = mClusterSets.get(mediaSets.get(expandedSetIndex));
+ if (clustering != null) {
+ ArrayList<Cluster> clusters = clustering.getClustersForDisplay();
+ int numClusters = clusters.size();
+ for (int i = 0; i < numClusters; i++) {
+ requestedItems += clusters.get(i).getNumExpectedItems();
+ }
+ }
+ }
+ MediaSet set = mediaSets.get(expandedSetIndex);
+ if (numItemsLoaded < set.getNumExpectedItems()) {
+ // We perform calculations for a window that gets anchored to a multiple of NUM_ITEMS_LOOKAHEAD.
+ // The start of the window is 0, x, 2x, 3x ... etc where x = NUM_ITEMS_LOOKAHEAD.
+ dataSource.loadItemsForSet(this, set, numItemsLoaded, (requestedItems / NUM_ITEMS_LOOKAHEAD)
+ * NUM_ITEMS_LOOKAHEAD + NUM_ITEMS_LOOKAHEAD);
+ if (set.getNumExpectedItems() == 0) {
+ mediaSets.remove(set);
+ mListener.onFeedChanged(this, false);
+ }
+ if (numItemsLoaded != set.mNumItemsLoaded && mListener != null) {
+ mListener.onFeedChanged(this, false);
+ }
+ }
+ }
+ MediaFilter filter = mMediaFilter;
+ if (filter != null && mMediaFilteredSet == null) {
+ if (expandedSetIndex != Shared.INVALID) {
+ MediaSet set = mediaSets.get(expandedSetIndex);
+ ArrayList<MediaItem> items = set.getItems();
+ int numItems = set.getNumItems();
+ MediaSet filteredSet = new MediaSet();
+ filteredSet.setNumExpectedItems(numItems);
+ mMediaFilteredSet = filteredSet;
+ for (int i = 0; i < numItems; ++i) {
+ MediaItem item = items.get(i);
+ if (filter.pass(item)) {
+ filteredSet.addItem(item);
+ }
+ }
+ filteredSet.updateNumExpectedItems();
+ filteredSet.generateTitle(true);
+ }
+ updateListener(true);
+ }
+ }
+ }
+ }
+ }
+
+ public void expandMediaSet(int mediaSetIndex) {
+ // We need to check if this slot can be focused or not.
+ if (mListener != null) {
+ mListener.onFeedAboutToChange(this);
+ }
+ if (mExpandedMediaSetIndex > 0 && mediaSetIndex == Shared.INVALID) {
+ // We are collapsing a previously expanded media set
+ if (mediaSetIndex < mMediaSets.size() && mExpandedMediaSetIndex >= 0 && mExpandedMediaSetIndex < mMediaSets.size()) {
+ MediaSet set = mMediaSets.get(mExpandedMediaSetIndex);
+ if (set.getNumItems() == 0) {
+ set.clear();
+ }
+ }
+ }
+ mExpandedMediaSetIndex = mediaSetIndex;
+ if (mediaSetIndex < mMediaSets.size() && mediaSetIndex >= 0) {
+ // Notify Picasa that the user entered the album.
+ // MediaSet set = mMediaSets.get(mediaSetIndex);
+ // PicasaService.requestSync(mContext,
+ // PicasaService.TYPE_ALBUM_PHOTOS, set.mPicasaAlbumId);
+ }
+ updateListener(true);
+ mMediaFeedNeedsToRun = true;
+ }
+
+ public boolean canExpandSet(int slotIndex) {
+ int mediaSetIndex = slotIndex;
+ if (mediaSetIndex < mMediaSets.size() && mediaSetIndex >= 0) {
+ MediaSet set = mMediaSets.get(mediaSetIndex);
+ if (set.getNumItems() > 0) {
+ MediaItem item = set.getItems().get(0);
+ if (item.mId == Shared.INVALID) {
+ return false;
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public boolean hasExpandedMediaSet() {
+ return (mExpandedMediaSetIndex != Shared.INVALID);
+ }
+
+ public boolean restorePreviousClusteringState() {
+ boolean retVal = disableClusteringIfNecessary();
+ if (retVal) {
+ if (mListener != null) {
+ mListener.onFeedAboutToChange(this);
+ }
+ updateListener(true);
+ mMediaFeedNeedsToRun = true;
+ }
+ return retVal;
+ }
+
+ private boolean disableClusteringIfNecessary() {
+ if (mInClusteringMode) {
+ // Disable clustering.
+ mInClusteringMode = false;
+ mMediaFeedNeedsToRun = true;
+ return true;
+ }
+ return false;
+ }
+
+ public boolean isClustered() {
+ return mInClusteringMode;
+ }
+
+ public MediaSet getCurrentSet() {
+ if (mExpandedMediaSetIndex != Shared.INVALID && mExpandedMediaSetIndex < mMediaSets.size()) {
+ return mMediaSets.get(mExpandedMediaSetIndex);
+ }
+ return null;
+ }
+
+ public void performClustering() {
+ if (mListener != null) {
+ mListener.onFeedAboutToChange(this);
+ }
+ MediaSet setToUse = null;
+ if (mExpandedMediaSetIndex != Shared.INVALID || mExpandedMediaSetIndex < mMediaSets.size()) {
+ setToUse = mMediaSets.get(mExpandedMediaSetIndex);
+ }
+ if (setToUse != null) {
+ MediaClustering clustering = null;
+ synchronized (mClusterSets) {
+ // Make sure the computation is completed to the end.
+ clustering = mClusterSets.get(setToUse);
+ if (clustering != null) {
+ clustering.compute(null, true);
+ } else {
+ return;
+ }
+ }
+ mInClusteringMode = true;
+ mMediaFeedNeedsToRun = true;
+ updateListener(true);
+ }
+ }
+
+ public void moveSetToFront(MediaSet mediaSet) {
+ ArrayList<MediaSet> mediaSets = mMediaSets;
+ int numSets = mediaSets.size();
+ if (numSets == 0) {
+ mediaSets.add(mediaSet);
+ return;
+ }
+ MediaSet setToFind = mediaSets.get(0);
+ if (setToFind == mediaSet) {
+ return;
+ }
+ mediaSets.set(0, mediaSet);
+ int indexToSwapTill = -1;
+ for (int i = 1; i < numSets; ++i) {
+ MediaSet set = mediaSets.get(i);
+ if (set == mediaSet) {
+ mediaSets.set(i, setToFind);
+ indexToSwapTill = i;
+ break;
+ }
+ }
+ if (indexToSwapTill != Shared.INVALID) {
+ for (int i = indexToSwapTill; i > 1; --i) {
+ MediaSet setEnd = mediaSets.get(i);
+ MediaSet setPrev = mediaSets.get(i - 1);
+ mediaSets.set(i, setPrev);
+ mediaSets.set(i - 1, setEnd);
+ }
+ }
+ mMediaFeedNeedsToRun = true;
+ }
+
+ public MediaSet replaceMediaSet(long setId, DataSource dataSource) {
+ MediaSet mediaSet = new MediaSet(dataSource);
+ mediaSet.mId = setId;
+ ArrayList<MediaSet> mediaSets = mMediaSets;
+ int numSets = mediaSets.size();
+ for (int i = 0; i < numSets; ++i) {
+ final MediaSet thisSet = mediaSets.get(i);
+ if (thisSet.mId == setId) {
+ mediaSet.mName = thisSet.mName;
+ mediaSet.mHasImages = thisSet.mHasImages;
+ mediaSet.mHasVideos = thisSet.mHasVideos;
+ mediaSets.set(i, mediaSet);
+ break;
+ }
+ }
+ mMediaFeedNeedsToRun = true;
+ return mediaSet;
+ }
+
+ public void setSingleImageMode(boolean singleImageMode) {
+ mSingleImageMode = singleImageMode;
+ }
+
+ public boolean isSingleImageMode() {
+ return mSingleImageMode;
+ }
+
+ public MediaSet getExpandedMediaSet() {
+ if (mExpandedMediaSetIndex == Shared.INVALID)
+ return null;
+ if (mExpandedMediaSetIndex >= mMediaSets.size())
+ return null;
+ return mMediaSets.get(mExpandedMediaSetIndex);
+ }
+}