package info.guardianproject.securereaderinterface.ui; import info.guardianproject.iocipher.File; import info.guardianproject.securereader.MediaDownloader.MediaDownloaderCallback; import info.guardianproject.securereaderinterface.App; import info.guardianproject.securereaderinterface.adapters.DownloadsAdapter; import info.guardianproject.securereaderinterface.views.ApplicationMediaContentPreviewView; import info.guardianproject.securereaderinterface.views.EPubMediaContentPreviewView; import info.guardianproject.securereaderinterface.views.ImageMediaContentPreviewView; import info.guardianproject.securereaderinterface.views.MediaContentPreviewView; import info.guardianproject.securereaderinterface.views.VideoMediaContentPreviewView; import java.util.ArrayList; import android.content.Context; import android.util.Log; import android.widget.ImageView.ScaleType; import com.google.common.base.Predicate; import com.google.common.collect.Iterables; import com.tinymission.rss.Item; import com.tinymission.rss.MediaContent; public class MediaViewCollection { public interface OnMediaLoadedListener { void onViewLoaded(MediaViewCollection collection, int index, boolean wasCached); } public static final String LOG = "MediaContentLoader"; private Context mContext; private Item mStory; private ArrayList<MediaContentLoadInfo> mLoadInfos; private ArrayList<MediaContentPreviewView> mViews; private ArrayList<OnMediaLoadedListener> mListeners; private boolean mHasBeenRecycled; private ScaleType mDefaultScaleType; private boolean mForceBitwiseDownloads; private boolean mUseThisThread; public MediaViewCollection(Context context, Item story) { mContext = context; mStory = story; mForceBitwiseDownloads = false; mUseThisThread = false; mDefaultScaleType = ScaleType.CENTER_CROP; mLoadInfos = new ArrayList<MediaContentLoadInfo>(); mViews = new ArrayList<MediaContentPreviewView>(); mListeners = new ArrayList<OnMediaLoadedListener>(); createLoadInfos(); } public void load(boolean forceBitwiseDownloads, boolean useThisThread) { mHasBeenRecycled = false; mForceBitwiseDownloads = forceBitwiseDownloads; mUseThisThread = useThisThread; createMediaViews(); for (MediaContentLoadInfo info : mLoadInfos) { info.load(mForceBitwiseDownloads); } } public Item getItem() { return mStory; } public void addListener(OnMediaLoadedListener listener) { synchronized(this) { if (!mListeners.contains(listener)) mListeners.add(listener); } } public void removeListener(OnMediaLoadedListener listener) { synchronized(this) { if (mListeners.contains(listener)) mListeners.remove(listener); } } private void createLoadInfos() { if (mStory != null) { for (int i = 0; i < mStory.getNumberOfMediaContent(); i++) { MediaContent mediaContent = mStory.getMediaContent(i); if (mediaContent == null || mediaContent.getUrl() == null || mediaContent.getType() == null) continue; MediaContentLoadInfo info = new MediaContentLoadInfo(mediaContent, i); mLoadInfos.add(info); } } } private void createMediaViews() { if (mViews == null || mViews.size() == 0) { for (MediaContentLoadInfo info : mLoadInfos) { createMediaView(info); } } } private void createMediaView(MediaContentLoadInfo content) { MediaContentPreviewView mediaView = null; // Create a view for it if (content.isVideo()) { VideoMediaContentPreviewView vmc = new VideoMediaContentPreviewView(mContext); vmc.setScaleType(mDefaultScaleType); mediaView = vmc; } else if (content.isApplication()) { ApplicationMediaContentPreviewView amc = new ApplicationMediaContentPreviewView(mContext); mediaView = amc; } else if (content.isEpub()) { EPubMediaContentPreviewView amc = new EPubMediaContentPreviewView(mContext); mediaView = amc; } else if (content.isAudio()) { VideoMediaContentPreviewView vmc = new VideoMediaContentPreviewView(mContext); mediaView = vmc; } else { ImageMediaContentPreviewView imc = new ImageMediaContentPreviewView(mContext); imc.setScaleType(mDefaultScaleType); mediaView = imc; } mViews.add(mediaView); } public ArrayList<MediaContentPreviewView> getViews() { return mViews; } public ArrayList<MediaContentPreviewView> getLoadedViews() { ArrayList<MediaContentPreviewView> views = null; if (mViews != null && mViews.size() > 0) { views = new ArrayList<MediaContentPreviewView>(); for (MediaContentPreviewView view : mViews) { if (view.getMediaContent() != null) views.add(view); } } return views; } public int getCount() { return mLoadInfos.size(); } public int getCountLoaded() { int n = 0; if (mViews != null && mViews.size() > 0) { for (MediaContentPreviewView view : mViews) { if (view.getMediaContent() != null) n++; } } return n; } /** * Stop loading */ public void recycle() { mHasBeenRecycled = true; for (MediaContentPreviewView view : getViews()) { view.recycle(); } mViews.clear(); } public class MediaContentLoadInfo implements MediaDownloaderCallback { public info.guardianproject.iocipher.File mFile; public java.io.File mFileNonVFS; private MediaContent mContent; private int mIndex; private boolean mIsLoading; private boolean mIsLoaded; private boolean mWasCached; private boolean mInConstructor; private boolean mNotifyDownloadsAdapter; public MediaContentLoadInfo(MediaContent content, int index) { mContent = content; mIndex = index; mInConstructor = true; mIsLoaded = mWasCached = App.getInstance().socialReader.loadMediaContent(content, this, false, false); mInConstructor = false; mNotifyDownloadsAdapter = false; } public void load(boolean forceBitwiseDownloads) { synchronized (this) { if (forceBitwiseDownloads) mNotifyDownloadsAdapter = true; if (mFile != null || mFileNonVFS != null) { onMediaAvailable(mContent, mIndex, mWasCached, mFileNonVFS, mFile); if (mNotifyDownloadsAdapter) DownloadsAdapter.downloaded(MediaViewCollection.this); } else { if (!isLoading()) { mIsLoading = true; if (!App.getInstance().socialReader.loadMediaContent(mContent, this, forceBitwiseDownloads)) mIsLoading = false; // Already loaded else if (mNotifyDownloadsAdapter) DownloadsAdapter.downloading(MediaViewCollection.this); } } } } public boolean isLoaded() { return mIsLoaded; } public boolean isLoading() { return mIsLoading; } public boolean isVideo() { return mContent.getType().startsWith("video/"); } public boolean isAudio() { return mContent.getType().startsWith("audio/"); } public boolean isApplication() { return mContent.getType().startsWith("application/vnd.android.package-archive"); } public boolean isEpub() { return mContent.getType().startsWith("application/epub+zip"); } @Override public void mediaDownloaded(File mediaFile) { synchronized (this) { mFile = mediaFile; mIsLoading = false; mIsLoaded = true; if (!mInConstructor) onMediaAvailable(mContent, mIndex, mWasCached, mFileNonVFS, mFile); if (mNotifyDownloadsAdapter) DownloadsAdapter.downloaded(MediaViewCollection.this); } } @Override public void mediaDownloadedNonVFS(java.io.File mediaFile) { synchronized (this) { mContent.setDownloadedNonVFSFile(mediaFile); mFileNonVFS = mediaFile; mIsLoading = false; mIsLoaded = true; if (!mInConstructor) onMediaAvailable(mContent, mIndex, mWasCached, mFileNonVFS, mFile); if (mNotifyDownloadsAdapter) DownloadsAdapter.downloaded(MediaViewCollection.this); }; } public MediaContent getMediaContent() { return mContent; } } public boolean containsLoadedMedia() { return Iterables.any(mLoadInfos, new Predicate<MediaContentLoadInfo>() { @Override public boolean apply(MediaContentLoadInfo info) { return info.isLoaded(); } }); } public void onMediaAvailable(MediaContent content, int index, boolean wasCached, java.io.File mediaFileNonVFS, info.guardianproject.iocipher.File mediaFile) { if (mHasBeenRecycled) { Log.v(LOG, "Media downloaded, but already recycled. Ignoring."); return; } MediaContentPreviewView mediaView = mViews.get(index); mediaView.setMediaContent(content, mediaFile, mediaFileNonVFS, mUseThisThread); ArrayList<OnMediaLoadedListener> listeners; synchronized(this) { listeners = new ArrayList<OnMediaLoadedListener>(mListeners); } for (OnMediaLoadedListener listener : listeners) listener.onViewLoaded(this, index, wasCached); } public boolean isLoadingMedia() { return Iterables.any(mLoadInfos, new Predicate<MediaContentLoadInfo>() { @Override public boolean apply(MediaContentLoadInfo info) { return info.isLoading(); } }); } public MediaContentPreviewView getFirstView() { for (MediaContentPreviewView v : mViews) { if (v != null) return v; } return null; } public MediaContentLoadInfo getFirstLoadInfo() { if (mLoadInfos != null && mLoadInfos.size() > 0) return mLoadInfos.get(0); return null; } public boolean isFirstViewPortrait() { MediaContentPreviewView first = getFirstView(); if (first != null && first.getMediaContent() != null) { return (first.getMediaContent().getHeight() > first.getMediaContent().getWidth()); } return false; } public void setScaleType(ScaleType scaleType) { if (scaleType != mDefaultScaleType) { mDefaultScaleType = scaleType; for (MediaContentPreviewView view : mViews) { if (view != null) { if (view instanceof ImageMediaContentPreviewView) { ((ImageMediaContentPreviewView) view).setScaleType(mDefaultScaleType); } else if (view instanceof VideoMediaContentPreviewView) { ((VideoMediaContentPreviewView) view).setScaleType(mDefaultScaleType); } } } } } }