[Android] [PATCH 06/11] Finer audio browsing

Geoffrey Métais geoffrey.metais at gmail.com
Mon Nov 17 17:53:43 CET 2014


---
 .../src/org/videolan/vlc/gui/tv/CardPresenter.java |  39 ++---
 .../src/org/videolan/vlc/gui/tv/GridFragment.java  | 175 +++++++++++++++++++--
 .../org/videolan/vlc/gui/tv/MainTvActivity.java    |  52 +++---
 .../vlc/gui/video/VideoBrowserInterface.java       |  11 +-
 4 files changed, 225 insertions(+), 52 deletions(-)

diff --git a/vlc-android/src/org/videolan/vlc/gui/tv/CardPresenter.java b/vlc-android/src/org/videolan/vlc/gui/tv/CardPresenter.java
index b1338ee..a070433 100644
--- a/vlc-android/src/org/videolan/vlc/gui/tv/CardPresenter.java
+++ b/vlc-android/src/org/videolan/vlc/gui/tv/CardPresenter.java
@@ -26,7 +26,6 @@ public class CardPresenter extends Presenter {
     private static Drawable sDefaultCardImage;
 
     static class ViewHolder extends Presenter.ViewHolder {
-        private Media mMedia;
         private ImageCardView mCardView;
 
         public ViewHolder(View view) {
@@ -34,14 +33,6 @@ public class CardPresenter extends Presenter {
             mCardView = (ImageCardView) view;
         }
 
-        public void setMovie(Media m) {
-            mMedia = m;
-        }
-
-        public Media getMovie() {
-            return mMedia;
-        }
-
         public ImageCardView getCardView() {
             return mCardView;
         }
@@ -80,16 +71,28 @@ public class CardPresenter extends Presenter {
 
     @Override
     public void onBindViewHolder(Presenter.ViewHolder viewHolder, Object item) {
-    	Media media = (Media) item;
-        ((ViewHolder) viewHolder).setMovie(media);
-
-        ((ViewHolder) viewHolder).mCardView.setTitleText(media.getTitle());
-        ((ViewHolder) viewHolder).mCardView.setContentText(media.getDescription());
         ((ViewHolder) viewHolder).mCardView.setMainImageDimensions(CARD_WIDTH, CARD_HEIGHT);
-        if (media.isPictureParsed())
-			((ViewHolder) viewHolder).updateCardViewImage(media.getLocation());
-		else
-			((ViewHolder) viewHolder).updateCardViewImage(sDefaultCardImage);
+    	if (item instanceof Media) {
+	    	Media media = (Media) item;
+	        ((ViewHolder) viewHolder).mCardView.setTitleText(media.getTitle());
+	        ((ViewHolder) viewHolder).mCardView.setContentText(media.getDescription());
+	        if (media.isPictureParsed())
+				((ViewHolder) viewHolder).updateCardViewImage(media.getLocation());
+			else
+				((ViewHolder) viewHolder).updateCardViewImage(sDefaultCardImage);
+    	} else if (item instanceof GridFragment.ListItem) {
+	    	GridFragment.ListItem listItem = (GridFragment.ListItem) item;
+	    	Media media = listItem.mMediaList.get(0);
+	        ((ViewHolder) viewHolder).mCardView.setTitleText(listItem.mTitle);
+	        ((ViewHolder) viewHolder).mCardView.setContentText(listItem.mSubTitle);
+	        if (media.isPictureParsed())
+				((ViewHolder) viewHolder).updateCardViewImage(media.getLocation());
+			else
+				((ViewHolder) viewHolder).updateCardViewImage(sDefaultCardImage);
+    	} else if (item instanceof String){
+    		((ViewHolder) viewHolder).mCardView.setTitleText((String) item);
+    		((ViewHolder) viewHolder).updateCardViewImage(sDefaultCardImage);
+    	}
     }
 
     @Override
diff --git a/vlc-android/src/org/videolan/vlc/gui/tv/GridFragment.java b/vlc-android/src/org/videolan/vlc/gui/tv/GridFragment.java
index 64a64ae..bfc1f14 100644
--- a/vlc-android/src/org/videolan/vlc/gui/tv/GridFragment.java
+++ b/vlc-android/src/org/videolan/vlc/gui/tv/GridFragment.java
@@ -20,7 +20,10 @@
 package org.videolan.vlc.gui.tv;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 import java.util.concurrent.BrokenBarrierException;
 import java.util.concurrent.CyclicBarrier;
 
@@ -29,10 +32,11 @@ import org.videolan.vlc.MediaDatabase;
 import org.videolan.vlc.MediaLibrary;
 import org.videolan.vlc.R;
 import org.videolan.vlc.Thumbnailer;
-import org.videolan.vlc.VLCApplication;
+import org.videolan.vlc.gui.audio.AudioUtil;
+import org.videolan.vlc.gui.audio.MediaComparators;
+import org.videolan.vlc.gui.tv.audioplayer.AudioPlayerActivity;
 import org.videolan.vlc.gui.video.VideoBrowserInterface;
 import org.videolan.vlc.gui.video.VideoListHandler;
-import org.videolan.vlc.gui.video.VideoPlayerActivity;
 import org.videolan.vlc.util.Util;
 
 import android.content.Context;
@@ -47,31 +51,46 @@ import android.support.v17.leanback.widget.Row;
 import android.support.v17.leanback.widget.VerticalGridPresenter;
 
 public class GridFragment extends VerticalGridFragment implements VideoBrowserInterface {
-	private static final String TAG = "VerticalGridFragment";
+	private static final String TAG = "VLC/GridFragment";
 
 	private static final int NUM_COLUMNS = 5;
 
 	protected final CyclicBarrier mBarrier = new CyclicBarrier(2);
 	protected Media mItemToUpdate;
+    private Map<String, ListItem> mMediaItemMap;
+    private ArrayList<ListItem> mMediaItemList;
 	private ArrayObjectAdapter mAdapter;
 	private MediaLibrary mMediaLibrary;
 	private Thumbnailer mThumbnailer;
 	HashMap<String, Integer> mMediaIndex;
 	Context mContext;
-	long mType;
+	String mCategory, mFilter;
+	long mType = -1;
 
 	@Override
 	public void onCreate(Bundle savedInstanceState) {
 		super.onCreate(savedInstanceState);
 		mContext = getActivity();
-		mType = getActivity().getIntent().getLongExtra("id", 0);
+		if (savedInstanceState != null){
+			mType = savedInstanceState.getLong(MEDIA_SECTION);
+			mCategory = savedInstanceState.getString(AUDIO_CATEGORY);
+			mFilter = savedInstanceState.getString(AUDIO_FILTER);
+		} else {
+			mType = getActivity().getIntent().getLongExtra(MEDIA_SECTION, -1);
+			mCategory = getActivity().getIntent().getStringExtra(AUDIO_CATEGORY);
+			mFilter = getActivity().getIntent().getStringExtra(AUDIO_FILTER);
+		}
 
-		setTitle(getString(R.string.app_name_full));
 
 		mMediaLibrary = MediaLibrary.getInstance();
-		if (mType == HEADER_VIDEO)
+		if (mType == HEADER_VIDEO) {
 			mThumbnailer = new Thumbnailer(mContext, getActivity().getWindowManager().getDefaultDisplay());
-		setupFragment();
+			setupFragment();
+		} else if (mType == HEADER_MUSIC) {
+			setupFragment();
+		} else {
+			setupFragmentForAudio();
+		}
 	}
 
 	public void onResume() {
@@ -94,6 +113,12 @@ public class GridFragment extends VerticalGridFragment implements VideoBrowserIn
 			mThumbnailer.stop();
 	}
 
+	public void onSaveInstanceState(Bundle outState){
+		super.onSaveInstanceState(outState);
+		outState.putLong(MEDIA_SECTION, mType);
+		outState.putString(AUDIO_CATEGORY, mCategory);
+	}
+
 	@Override
 	public void onDestroy() {
 		super.onDestroy();
@@ -102,7 +127,96 @@ public class GridFragment extends VerticalGridFragment implements VideoBrowserIn
 		mBarrier.reset();
 	}
 
+	private void setupFragmentForAudio() {
+		Bitmap picture;
+		String title;
+		mMediaItemMap = new HashMap<String, ListItem>();
+		mMediaItemList = new ArrayList<GridFragment.ListItem>();
+		VerticalGridPresenter gridPresenter = new VerticalGridPresenter();
+		mAdapter = new ArrayObjectAdapter(new CardPresenter());
+		gridPresenter.setNumberOfColumns(NUM_COLUMNS);
+		setGridPresenter(gridPresenter);
+
+		List<Media> audioList = MediaLibrary.getInstance().getAudioItems();
+		if (getString(R.string.artists).equals(mCategory)){
+			Collections.sort(audioList, MediaComparators.byArtist);
+			title = getString(R.string.artists);
+			for (Media media : audioList){
+				add(media.getArtist(), null, media);
+			}
+		} else if (getString(R.string.albums).equals(mCategory)){
+			title = getString(R.string.albums);
+			Collections.sort(audioList, MediaComparators.byAlbum);
+			for (Media media : audioList){
+				if (mFilter == null 
+						|| (mType == FILTER_ARTIST && mFilter.equals(media.getArtist()))
+						|| (mType == FILTER_GENRE && mFilter.equals(media.getGenre())))
+				add(media.getAlbum(), media.getArtist(), media);
+			}
+			//Customize title for artist/genre browsing
+			if (mType == FILTER_ARTIST){
+				title = title + " " + mMediaItemList.get(0).mMediaList.get(0).getArtist();
+			} else if (mType == FILTER_GENRE){
+				title = title + " " + mMediaItemList.get(0).mMediaList.get(0).getGenre();
+			}
+		} else if (getString(R.string.genres).equals(mCategory)){
+			title = getString(R.string.genres);
+			Collections.sort(audioList, MediaComparators.byGenre);
+			for (Media media : audioList){
+				add(media.getGenre(), null, media);
+			}
+		} else if (getString(R.string.songs).equals(mCategory)){
+			title = getString(R.string.songs);
+			Collections.sort(audioList, MediaComparators.byName);
+			for (Media media : audioList){
+				add(media.getTitle(), media.getArtist(), media);
+			}
+		} else {
+			title = getString(R.string.app_name_full);
+		}
+		setTitle(title);
+		//check for pictures
+		for (Media media : audioList){
+			picture = AudioUtil.getCover(mContext, media, 320);
+			if (picture != null){
+				MediaDatabase.setPicture(media, picture);
+				picture = null;
+			}
+		}
+		mAdapter.addAll(0, mMediaItemList);
+		setAdapter(mAdapter);
+
+		setOnItemClickedListener(new OnItemClickedListener() {
+			@Override
+			public void onItemClicked(Object item, Row row) {
+				ListItem listItem = (ListItem) item;
+				Intent intent;
+				if (getString(R.string.artists).equals(mCategory)){
+					intent = new Intent(mContext, VerticalGridActivity.class);
+					intent.putExtra(AUDIO_CATEGORY, getString(R.string.albums));
+					intent.putExtra(MEDIA_SECTION, FILTER_ARTIST);
+					intent.putExtra(AUDIO_FILTER, listItem.mMediaList.get(0).getArtist());
+				} else if (getString(R.string.genres).equals(mCategory)){
+					intent = new Intent(mContext, VerticalGridActivity.class);
+					intent.putExtra(AUDIO_CATEGORY, getString(R.string.albums));
+					intent.putExtra(MEDIA_SECTION, FILTER_GENRE);
+					intent.putExtra(AUDIO_FILTER, listItem.mMediaList.get(0).getGenre());
+				} else {
+					ArrayList<String> locations = new ArrayList<String>();
+					for (Media media : listItem.mMediaList){
+						locations.add(media.getLocation());
+					}
+					intent = new Intent(mContext, AudioPlayerActivity.class);
+					intent.putExtra("locations", locations);
+				}
+				startActivity(intent);
+			}
+		});
+	}
+
+	//TODO shrink audio part, I keep it for now just in case...
 	private void setupFragment() {
+		setTitle(getString(R.string.app_name_full));
 		int size;
 		Media media;
 		Bitmap picture;
@@ -118,7 +232,7 @@ public class GridFragment extends VerticalGridFragment implements VideoBrowserIn
 		ArrayList<Media> mediaList = null;
 		if (mType == HEADER_VIDEO)
 			mediaList = mMediaLibrary.getVideoItems();
-		else if (mType == HEADER_MUSIC)
+		else
 			mediaList = mMediaLibrary.getAudioItems();
 		size = mediaList == null ? 0 : mediaList.size();
 		mMediaIndex = new HashMap<String, Integer>(size);
@@ -135,6 +249,12 @@ public class GridFragment extends VerticalGridFragment implements VideoBrowserIn
 					MediaDatabase.setPicture(media, picture);
 					picture = null;
 				}
+			} else {
+				picture = AudioUtil.getCover(mContext, media, 320);
+				if (picture != null){
+					MediaDatabase.setPicture(media, picture);
+					picture = null;
+				}
 			}
 		}
 
@@ -143,16 +263,15 @@ public class GridFragment extends VerticalGridFragment implements VideoBrowserIn
 		/*setOnItemSelectedListener(new OnItemSelectedListener() {
 			@Override
 			public void onItemSelected(Object item, Row row) {
+				setTitle(((Media )item).getTitle());
 			}
 		});*/
 
 		setOnItemClickedListener(new OnItemClickedListener() {
 			@Override
 			public void onItemClicked(Object item, Row row) {
-				Media media = (Media)item;
-				if (media.getType() == Media.TYPE_VIDEO){
-					VideoPlayerActivity.start(getActivity(), media.getLocation(), false);
-				}
+				Media media = (Media) item;
+				TvUtil.openMedia(getActivity(), media, null);
 			}
 		});
 	}
@@ -184,4 +303,34 @@ public class GridFragment extends VerticalGridFragment implements VideoBrowserIn
 	};
 
 	private Handler mHandler = new VideoListHandler(this);
+
+	// An item of the list: a media or a separator.
+    public class ListItem {
+        public String mTitle;
+        public String mSubTitle;
+        public ArrayList<Media> mMediaList;
+        public boolean mIsSeparator;
+
+        public ListItem(String title, String subTitle, Media media, boolean isSeparator) {
+            mMediaList = new ArrayList<Media>();
+            if (media != null)
+                mMediaList.add(media);
+            mTitle = title;
+            mSubTitle = subTitle;
+            mIsSeparator = isSeparator;
+        }
+    }
+
+    public void add(String title, String subTitle, Media media) {
+        if(title == null) return;
+        title = title.trim();
+        if(subTitle != null) subTitle = subTitle.trim();
+        if (mMediaItemMap.containsKey(title))
+            mMediaItemMap.get(title).mMediaList.add(media);
+        else {
+            ListItem item = new ListItem(title, subTitle, media, false);
+            mMediaItemMap.put(title, item);
+            mMediaItemList.add(item);
+        }
+    }
 }
\ No newline at end of file
diff --git a/vlc-android/src/org/videolan/vlc/gui/tv/MainTvActivity.java b/vlc-android/src/org/videolan/vlc/gui/tv/MainTvActivity.java
index 5f8d137..e3c1558 100644
--- a/vlc-android/src/org/videolan/vlc/gui/tv/MainTvActivity.java
+++ b/vlc-android/src/org/videolan/vlc/gui/tv/MainTvActivity.java
@@ -30,7 +30,6 @@ import org.videolan.vlc.MediaDatabase;
 import org.videolan.vlc.MediaLibrary;
 import org.videolan.vlc.R;
 import org.videolan.vlc.Thumbnailer;
-import org.videolan.vlc.gui.audio.AudioUtil;
 import org.videolan.vlc.gui.tv.audioplayer.AudioPlayerActivity;
 import org.videolan.vlc.gui.video.VideoBrowserInterface;
 import org.videolan.vlc.gui.video.VideoListHandler;
@@ -52,7 +51,6 @@ import android.support.v17.leanback.widget.ListRow;
 import android.support.v17.leanback.widget.ListRowPresenter;
 import android.support.v17.leanback.widget.OnItemClickedListener;
 import android.support.v17.leanback.widget.Row;
-import android.util.Log;
 import android.view.View;
 import android.view.View.OnClickListener;
 
@@ -60,7 +58,7 @@ public class MainTvActivity extends Activity implements VideoBrowserInterface {
 
 	private static final int NUM_ITEMS_PREVIEW = 5;
 
-	public static final String TAG = "BrowseActivity";
+	public static final String TAG = "VLC/MainTvActivity";
 
 	protected BrowseFragment mBrowseFragment;
 	protected final CyclicBarrier mBarrier = new CyclicBarrier(2);
@@ -68,8 +66,9 @@ public class MainTvActivity extends Activity implements VideoBrowserInterface {
 	private Thumbnailer mThumbnailer;
 	private Media mItemToUpdate;
 	ArrayObjectAdapter mRowsAdapter;
-	ArrayObjectAdapter videoAdapter;
-	ArrayObjectAdapter audioAdapter;
+	ArrayObjectAdapter mVideoAdapter;
+	ArrayObjectAdapter mAudioAdapter;
+	ArrayObjectAdapter mCategoriesAdapter;
 	HashMap<String, Integer> mVideoIndex;
 	Drawable mDefaultBackground;
 	Activity mContext;
@@ -77,7 +76,13 @@ public class MainTvActivity extends Activity implements VideoBrowserInterface {
 	OnItemClickedListener mItemClickListener = new OnItemClickedListener() {
 		@Override
 		public void onItemClicked(Object item, Row row) {
-			TvUtil.openMedia(mContext, (Media)item, row);
+			if (row.getId() == HEADER_CATEGORIES){
+				String category = (String)item;
+				Intent intent = new Intent(mContext, VerticalGridActivity.class);
+				intent.putExtra(AUDIO_CATEGORY, category);
+				startActivity(intent);
+			} else
+				TvUtil.openMedia(mContext, (Media)item, row);
 		}
 	};
 
@@ -93,7 +98,7 @@ public class MainTvActivity extends Activity implements VideoBrowserInterface {
 	protected void onCreate(Bundle savedInstanceState) {
 		super.onCreate(savedInstanceState);
 		/*
-		 * skip browser and show direcly Audio Player if a song is playing
+		 * skip browser and show directly Audio Player if a song is playing
 		 */
 		if (LibVLC.getExistingInstance() != null){
 			if (LibVLC.getExistingInstance().isPlaying()){
@@ -183,7 +188,7 @@ public class MainTvActivity extends Activity implements VideoBrowserInterface {
 	}
 
 	public void updateItem() {
-		videoAdapter.notifyArrayItemRangeChanged(mVideoIndex.get(mItemToUpdate.getLocation()), 1);
+		mVideoAdapter.notifyArrayItemRangeChanged(mVideoIndex.get(mItemToUpdate.getLocation()), 1);
 		try {
 			mBarrier.await();
 		} catch (InterruptedException e) {
@@ -204,7 +209,7 @@ public class MainTvActivity extends Activity implements VideoBrowserInterface {
 		protected Void doInBackground(Void... params) {
 			MediaDatabase mediaDatabase = MediaDatabase.getInstance();
 			ArrayList<Media> videoList = mMediaLibrary.getVideoItems();
-			ArrayList<Media> audioList = mMediaLibrary.getAudioItems();
+//			ArrayList<Media> audioList = mMediaLibrary.getAudioItems();
 			int size;
 			Media item;
 			Bitmap picture;
@@ -213,7 +218,7 @@ public class MainTvActivity extends Activity implements VideoBrowserInterface {
 			if (!videoList.isEmpty()) {
 				size = videoList.size();
 				mVideoIndex = new HashMap<String, Integer>(size);
-				videoAdapter = new ArrayObjectAdapter(
+				mVideoAdapter = new ArrayObjectAdapter(
 						new CardPresenter());
 				if (NUM_ITEMS_PREVIEW < size)
 					size = NUM_ITEMS_PREVIEW;
@@ -221,7 +226,7 @@ public class MainTvActivity extends Activity implements VideoBrowserInterface {
 					item = videoList.get(i);
 					picture = mediaDatabase.getPicture(mContext, item.getLocation());
 
-					videoAdapter.add(item);
+					mVideoAdapter.add(item);
 					mVideoIndex.put(item.getLocation(), i);
 					if (mThumbnailer != null){
 						if (picture== null) {
@@ -233,18 +238,18 @@ public class MainTvActivity extends Activity implements VideoBrowserInterface {
 					}
 				}
 				// Empty item to launch grid activity
-				videoAdapter.add(new Media(null, 0, 0, Media.TYPE_GROUP, null, "Browse more", null, null, null, 0, 0, null, 0, 0));
+				mVideoAdapter.add(new Media(null, 0, 0, Media.TYPE_GROUP, null, "Browse more", null, null, null, 0, 0, null, 0, 0));
 
 				HeaderItem header = new HeaderItem(HEADER_VIDEO, getString(R.string.video), null);
-				mRowsAdapter.add(new ListRow(header, videoAdapter));
+				mRowsAdapter.add(new ListRow(header, mVideoAdapter));
 			}
 
-			// update audio section
+			/*// update audio section
 			if (!audioList.isEmpty()) {
 				size = audioList.size();
 				if (NUM_ITEMS_PREVIEW < size)
 					size = NUM_ITEMS_PREVIEW;
-				audioAdapter = new ArrayObjectAdapter(new CardPresenter());
+				mAudioAdapter = new ArrayObjectAdapter(new CardPresenter());
 				for (int i = 0 ; i < size ; ++i) {
 					item = audioList.get(i);
 					picture = AudioUtil.getCover(mContext, item, 320);
@@ -252,15 +257,24 @@ public class MainTvActivity extends Activity implements VideoBrowserInterface {
 						MediaDatabase.setPicture(item, picture);
 						picture = null;
 					}
-					audioAdapter.add(item);
+					mAudioAdapter.add(item);
 
 				}
 				// Empty item to launch grid activity
-				audioAdapter.add(new Media(null, 0, 0, Media.TYPE_GROUP, null, "Browse more", null, null, null, 0, 0, null, 0, 0));
+				mAudioAdapter.add(new Media(null, 0, 0, Media.TYPE_GROUP, null, "Browse more", null, null, null, 0, 0, null, 0, 0));
 
 				HeaderItem header = new HeaderItem(HEADER_MUSIC, getString(R.string.audio), null);
-				mRowsAdapter.add(new ListRow(header, audioAdapter));
-			}
+				mRowsAdapter.add(new ListRow(header, mAudioAdapter));
+			}*/
+
+			mCategoriesAdapter = new ArrayObjectAdapter(new CardPresenter());
+			mCategoriesAdapter.add(getString(R.string.artists));
+			mCategoriesAdapter.add(getString(R.string.albums));
+			mCategoriesAdapter.add(getString(R.string.genres));
+			mCategoriesAdapter.add(getString(R.string.songs));
+			HeaderItem header = new HeaderItem(HEADER_CATEGORIES, getString(R.string.audio), null);
+			mRowsAdapter.add(new ListRow(header, mCategoriesAdapter));
+
 			return null;
 		}
 
diff --git a/vlc-android/src/org/videolan/vlc/gui/video/VideoBrowserInterface.java b/vlc-android/src/org/videolan/vlc/gui/video/VideoBrowserInterface.java
index 84efc01..b06a5e7 100644
--- a/vlc-android/src/org/videolan/vlc/gui/video/VideoBrowserInterface.java
+++ b/vlc-android/src/org/videolan/vlc/gui/video/VideoBrowserInterface.java
@@ -5,8 +5,15 @@ import java.util.concurrent.BrokenBarrierException;
 import org.videolan.libvlc.Media;
 
 public interface VideoBrowserInterface {
-    public static final int HEADER_VIDEO = 0;
-	public static final int HEADER_MUSIC = 1;
+    public static final long HEADER_VIDEO = 0;
+	public static final long HEADER_MUSIC = 1;
+	public static final long HEADER_CATEGORIES = 2;
+	public static final long FILTER_ARTIST = 3;
+	public static final long FILTER_GENRE = 4;
+
+	public static final String MEDIA_SECTION = "id";
+	public static final String AUDIO_CATEGORY = "category";
+	public static final String AUDIO_FILTER = "filter";
 
 	public void resetBarrier();
 	public void setItemToUpdate(Media item);
-- 
1.9.1



More information about the Android mailing list