Commit fc83d224 authored by Geoffrey Métais's avatar Geoffrey Métais

Network browser refactoring fot TV

Line organized browsing, like main App screen and Android TV Launcher
parent 69f1012d
......@@ -39,6 +39,7 @@ import org.videolan.vlc.gui.audio.MediaComparators;
import org.videolan.vlc.gui.browser.BaseBrowserFragment;
import org.videolan.vlc.gui.tv.DetailsActivity;
import org.videolan.vlc.gui.tv.MediaItemDetails;
import org.videolan.vlc.gui.tv.browser.interfaces.BrowserActivityInterface;
import org.videolan.vlc.util.VLCInstance;
import java.util.ArrayList;
......@@ -73,7 +74,7 @@ public class BrowserGridFragment extends GridFragment implements MediaBrowser.Ev
mMediaBrowser.browse(mUri);
else
mMediaBrowser.discoverNetworkShares();
((BrowserActivity)getActivity()).showProgress(true);
((BrowserActivityInterface)getActivity()).showProgress(true);
}
}
setOnItemViewClickedListener(mClickListener);
......@@ -85,7 +86,7 @@ public class BrowserGridFragment extends GridFragment implements MediaBrowser.Ev
mMediaBrowser.release();
mMediaBrowser = null;
}
((BrowserActivity)getActivity()).updateEmptyView(false);
((BrowserActivityInterface)getActivity()).updateEmptyView(false);
}
@Override
public void onMediaAdded(int index, Media media) {
......@@ -98,7 +99,7 @@ public class BrowserGridFragment extends GridFragment implements MediaBrowser.Ev
mAdapter.clear();
mAdapter.addAll(0, mMediaList); //FIXME adding 1 by 1 doesn't work
}
((BrowserActivity)getActivity()).showProgress(false);
((BrowserActivityInterface)getActivity()).showProgress(false);
}
@Override
......@@ -106,8 +107,8 @@ public class BrowserGridFragment extends GridFragment implements MediaBrowser.Ev
@Override
public void onBrowseEnd() {
((BrowserActivity)getActivity()).showProgress(false);
((BrowserActivity)getActivity()).updateEmptyView(mMediaList.isEmpty());
((BrowserActivityInterface)getActivity()).showProgress(false);
((BrowserActivityInterface)getActivity()).updateEmptyView(mMediaList.isEmpty());
sortList();
}
......
......@@ -32,13 +32,9 @@ import android.support.v17.leanback.widget.VerticalGridPresenter;
import org.videolan.vlc.gui.tv.CardPresenter;
import org.videolan.vlc.gui.tv.TvUtil;
import org.videolan.vlc.gui.tv.browser.interfaces.BrowserFragmentInterface;
public class GridFragment extends VerticalGridFragment {
public interface BrowserActivity {
public void showProgress(boolean show);
public void updateEmptyView(boolean empty);
}
public class GridFragment extends VerticalGridFragment implements BrowserFragmentInterface {
protected static final String TAG = "VLC/GridFragment";
......@@ -67,7 +63,7 @@ public class GridFragment extends VerticalGridFragment {
}
};
protected void refresh() {}
public void refresh() {}
protected void updateList() {}
public void updateList() {}
}
\ No newline at end of file
......@@ -55,10 +55,10 @@ public abstract class MediaLibBrowserFragment extends GridFragment {
mBarrier.reset();
}
protected void refresh() {
public void refresh() {
if (!mMediaLibrary.isWorking())
mMediaLibrary.loadMediaItems(true);
}
protected void updateList() {}
public void updateList() {}
}
......@@ -39,6 +39,7 @@ import org.videolan.vlc.R;
import org.videolan.vlc.gui.tv.MainTvActivity;
import org.videolan.vlc.gui.audio.MediaComparators;
import org.videolan.vlc.gui.tv.audioplayer.AudioPlayerActivity;
import org.videolan.vlc.gui.tv.browser.interfaces.BrowserActivityInterface;
import org.videolan.vlc.util.WeakHandler;
import java.util.ArrayList;
......@@ -115,7 +116,7 @@ public class MusicFragment extends MediaLibBrowserFragment {
mAdapter.clear();
mMediaItemMap = new HashMap<String, ListItem>();
mMediaItemList = new ArrayList<ListItem>();
((BrowserActivity)getActivity()).showProgress(true);
((BrowserActivityInterface)getActivity()).showProgress(true);
}
@Override
......@@ -180,7 +181,7 @@ public class MusicFragment extends MediaLibBrowserFragment {
@Override
protected void onPostExecute(String title) {
((BrowserActivity)getActivity()).showProgress(false);
((BrowserActivityInterface)getActivity()).showProgress(false);
setTitle(title);
setOnItemViewClickedListener(new OnItemViewClickedListener() {
@Override
......@@ -238,14 +239,14 @@ public class MusicFragment extends MediaLibBrowserFragment {
}
}
public ListItem add(String title, String subTitle, MediaWrapper MediaWrapper) {
public ListItem add(String title, String subTitle, MediaWrapper mediaWrapper) {
if(title == null) return null;
title = title.trim();
if(subTitle != null) subTitle = subTitle.trim();
if (mMediaItemMap.containsKey(title))
mMediaItemMap.get(title).mediaList.add(MediaWrapper);
mMediaItemMap.get(title).mediaList.add(mediaWrapper);
else {
ListItem item = new ListItem(title, subTitle, MediaWrapper);
ListItem item = new ListItem(title, subTitle, mediaWrapper);
mMediaItemMap.put(title, item);
mMediaItemList.add(item);
return item;
......@@ -254,7 +255,7 @@ public class MusicFragment extends MediaLibBrowserFragment {
}
@Override
protected void updateList() {
public void updateList() {
if (mUpdater == null) {
mUpdater = new AsyncAudioUpdate();
mUpdater.execute();
......
/*
* *************************************************************************
* NetworkBrowseFragment.java
* **************************************************************************
* Copyright © 2015 VLC authors and VideoLAN
* Author: Geoffrey Métais
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
* ***************************************************************************
*/
package org.videolan.vlc.gui.tv.browser;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Message;
import android.os.Parcelable;
import android.support.v17.leanback.app.BrowseFragment;
import android.support.v17.leanback.widget.ArrayObjectAdapter;
import android.support.v17.leanback.widget.HeaderItem;
import android.support.v17.leanback.widget.ListRow;
import android.support.v17.leanback.widget.ListRowPresenter;
import android.support.v17.leanback.widget.OnItemViewClickedListener;
import android.support.v17.leanback.widget.OnItemViewSelectedListener;
import android.support.v17.leanback.widget.Presenter;
import android.support.v17.leanback.widget.Row;
import android.support.v17.leanback.widget.RowPresenter;
import android.util.Log;
import org.videolan.libvlc.Media;
import org.videolan.libvlc.util.MediaBrowser;
import org.videolan.vlc.MediaWrapper;
import org.videolan.vlc.R;
import org.videolan.vlc.gui.audio.MediaComparators;
import org.videolan.vlc.gui.browser.BaseBrowserFragment;
import org.videolan.vlc.gui.tv.CardPresenter;
import org.videolan.vlc.gui.tv.DetailsActivity;
import org.videolan.vlc.gui.tv.MediaItemDetails;
import org.videolan.vlc.gui.tv.TvUtil;
import org.videolan.vlc.gui.tv.browser.interfaces.BrowserActivityInterface;
import org.videolan.vlc.gui.tv.browser.interfaces.BrowserFragmentInterface;
import org.videolan.vlc.util.VLCInstance;
import org.videolan.vlc.util.WeakHandler;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
public class NetworkBrowserFragment extends BrowseFragment implements BrowserFragmentInterface, MediaBrowser.EventListener, OnItemViewSelectedListener, OnItemViewClickedListener {
public static final String TAG = "VLC/NetworkBrowserFragment";
public static final String SELECTED_ITEM = "selected";
public static int UPDATE_DISPLAY = 1;
ArrayObjectAdapter mAdapter = new ArrayObjectAdapter(new ListRowPresenter());
private MediaBrowser mMediaBrowser;
private MediaWrapper mItemSelected;
protected Map<String, ListItem> mMediaItemMap = new HashMap<String, ListItem>();
private NetworkHandler mHandler = new NetworkHandler(this);
private Uri mUri;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null){
String mrl = savedInstanceState.getString(BaseBrowserFragment.KEY_MRL);
if (mrl != null)
mUri = Uri.parse(mrl);
mItemSelected = savedInstanceState.getParcelable(SELECTED_ITEM);
} else {
Intent intent = getActivity().getIntent();
if (intent != null && intent.hasExtra(BaseBrowserFragment.KEY_MRL))
mUri = Uri.parse(intent.getStringExtra(BaseBrowserFragment.KEY_MRL));
}
setOnItemViewClickedListener(this);
setOnItemViewSelectedListener(this);
setAdapter(mAdapter);
// UI setting
setHeadersState(HEADERS_ENABLED);
setBrandColor(getResources().getColor(R.color.orange800));
}
public void onResume() {
super.onResume();
if (mAdapter.size() == 0) {
browse();
}
}
public void onPause(){
super.onPause();
if (mMediaBrowser != null) {
mMediaBrowser.release();
mMediaBrowser = null;
}
((BrowserActivityInterface)getActivity()).updateEmptyView(false);
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (mUri != null)
outState.putString(BaseBrowserFragment.KEY_MRL, mUri.toString());
if (mItemSelected != null) {
outState.putParcelable(SELECTED_ITEM, mItemSelected);
}
}
private void browse() {
mMediaBrowser = new MediaBrowser(VLCInstance.get(), this);
if (mMediaBrowser != null) {
if (mUri != null)
mMediaBrowser.browse(mUri);
else
mMediaBrowser.discoverNetworkShares();
((BrowserActivityInterface)getActivity()).showProgress(true);
}
}
@Override
public void refresh() {
mAdapter.clear();
browse();
}
private void sort(){
new Thread(new Runnable() {
@Override
public void run() {
mMediaItemMap = new TreeMap<>(mMediaItemMap); //sort sections
for (ListItem item : mMediaItemMap.values()) {
Collections.sort(item.mediaList, MediaComparators.byName);
}
mHandler.sendEmptyMessage(UPDATE_DISPLAY);
}
}).start();
}
@Override
public void updateList() {
mAdapter.clear();
ArrayObjectAdapter adapter;
HeaderItem header;
for (ListItem item : mMediaItemMap.values()){
adapter = new ArrayObjectAdapter(new CardPresenter(getActivity()));
header = new HeaderItem(0, item.Letter);
adapter.addAll(0, item.mediaList);
mAdapter.add(new ListRow(header, adapter));
}
((BrowserActivityInterface)getActivity()).updateEmptyView(mAdapter.size() == 0);
}
private void addMedia(Media media){
addMedia(new MediaWrapper(media));
}
private void addMedia(MediaWrapper media){
int type = media.getType();
if (type != MediaWrapper.TYPE_AUDIO && type != MediaWrapper.TYPE_VIDEO && type != MediaWrapper.TYPE_DIR)
return;
String letter = media.getTitle().substring(0, 1).toUpperCase();
if (mMediaItemMap.containsKey(letter)){
mMediaItemMap.get(letter).mediaList.add(media);
} else {
ListItem item = new ListItem(letter, media);
mMediaItemMap.put(letter, item);
}
}
public void onMediaAdded(int index, Media media) {
addMedia(media);
if (mUri == null) { // we are at root level
sort();
}
((BrowserActivityInterface)getActivity()).showProgress(false);
}
public void onMediaRemoved(int index, Media media) {}
public void onBrowseEnd() {
((BrowserActivityInterface)getActivity()).showProgress(false);
((BrowserActivityInterface)getActivity()).updateEmptyView(mAdapter.size() == 0);
sort();
}
public void showDetails() {
if (mItemSelected == null)
return;
if (mItemSelected.getType() == MediaWrapper.TYPE_DIR) {
Intent intent = new Intent(getActivity(),
DetailsActivity.class);
// pass the item information
intent.putExtra("media", mItemSelected);
intent.putExtra("item", (Parcelable) new MediaItemDetails(mItemSelected.getTitle(), mItemSelected.getArtist(), mItemSelected.getAlbum(), mItemSelected.getLocation()));
startActivity(intent);
}
}
@Override
public void onItemSelected(Presenter.ViewHolder itemViewHolder, Object item, RowPresenter.ViewHolder rowViewHolder, Row row) {
mItemSelected = (MediaWrapper)item;
}
@Override
public void onItemClicked(Presenter.ViewHolder viewHolder, Object item, RowPresenter.ViewHolder viewHolder1, Row row) {
TvUtil.openMedia(getActivity(), item, null);
}
public static class ListItem {
public String Letter;
public ArrayList<MediaWrapper> mediaList;
public ListItem(String letter, MediaWrapper MediaWrapper) {
mediaList = new ArrayList<MediaWrapper>();
if (MediaWrapper != null)
mediaList.add(MediaWrapper);
Letter = letter;
}
}
private class NetworkHandler extends WeakHandler<NetworkBrowserFragment> {
public NetworkHandler(NetworkBrowserFragment owner) {
super(owner);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
NetworkBrowserFragment owner = getOwner();
if (owner != null && msg.what == UPDATE_DISPLAY)
owner.updateList();
}
}
}
......@@ -20,9 +20,8 @@
*****************************************************************************/
package org.videolan.vlc.gui.tv.browser;
import android.content.Intent;
import android.app.Fragment;
import android.os.Bundle;
import android.support.v17.leanback.app.BackgroundManager;
import android.view.KeyEvent;
import android.view.View;
import android.widget.ProgressBar;
......@@ -30,11 +29,12 @@ import android.widget.TextView;
import org.videolan.vlc.R;
import org.videolan.vlc.gui.tv.MainTvActivity;
import org.videolan.vlc.gui.tv.SearchActivity;
import org.videolan.vlc.gui.tv.browser.interfaces.BrowserActivityInterface;
import org.videolan.vlc.gui.tv.browser.interfaces.BrowserFragmentInterface;
public class VerticalGridActivity extends BaseTvActivity implements GridFragment.BrowserActivity {
public class VerticalGridActivity extends BaseTvActivity implements BrowserActivityInterface {
GridFragment mFragment;
BrowserFragmentInterface mFragment;
ProgressBar mContentLoadingProgressBar;
TextView mEmptyView;
......@@ -51,13 +51,13 @@ public class VerticalGridActivity extends BaseTvActivity implements GridFragment
else if (type == MainTvActivity.HEADER_CATEGORIES)
mFragment = new MusicFragment();
else if (type == MainTvActivity.HEADER_NETWORK)
mFragment = new BrowserGridFragment();
mFragment = new NetworkBrowserFragment();
else {
finish();
return;
}
getFragmentManager().beginTransaction()
.add(R.id.tv_fragment_placeholder, mFragment)
.add(R.id.tv_fragment_placeholder, (Fragment) mFragment)
.commit();
}
......@@ -72,8 +72,8 @@ public class VerticalGridActivity extends BaseTvActivity implements GridFragment
}
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (mFragment instanceof BrowserGridFragment && (keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE || keyCode == KeyEvent.KEYCODE_BUTTON_Y || keyCode == KeyEvent.KEYCODE_Y)) {
((BrowserGridFragment)mFragment).showDetails();
if (mFragment instanceof NetworkBrowserFragment && (keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE || keyCode == KeyEvent.KEYCODE_BUTTON_Y || keyCode == KeyEvent.KEYCODE_Y)) {
((NetworkBrowserFragment)mFragment).showDetails();
return true;
}
return super.onKeyDown(keyCode, event);
......
......@@ -31,6 +31,7 @@ import org.videolan.vlc.MediaWrapper;
import org.videolan.vlc.R;
import org.videolan.vlc.Thumbnailer;
import org.videolan.vlc.gui.tv.MainTvActivity;
import org.videolan.vlc.gui.tv.browser.interfaces.BrowserActivityInterface;
import org.videolan.vlc.gui.video.VideoListHandler;
import org.videolan.vlc.interfaces.IVideoBrowser;
......@@ -77,7 +78,7 @@ public class VideoGridFragment extends MediaLibBrowserFragment implements IVideo
protected void onPreExecute(){
setTitle(getString(R.string.app_name_full));
mAdapter.clear();
((BrowserActivity)getActivity()).showProgress(true);
((BrowserActivityInterface)getActivity()).showProgress(true);
}
@Override
protected Void doInBackground(Void... params) {
......@@ -102,7 +103,7 @@ public class VideoGridFragment extends MediaLibBrowserFragment implements IVideo
@Override
protected void onPostExecute(Void result) {
((BrowserActivity)getActivity()).showProgress(false);
((BrowserActivityInterface)getActivity()).showProgress(false);
setOnItemViewClickedListener(mClickListener);
}
}
......
/*
* *************************************************************************
* BrowserActivityInterface.java
* **************************************************************************
* Copyright © 2015 VLC authors and VideoLAN
* Author: Geoffrey Métais
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
* ***************************************************************************
*/
package org.videolan.vlc.gui.tv.browser.interfaces;
public interface BrowserActivityInterface {
void showProgress(boolean show);
void updateEmptyView(boolean empty);
}
/*
* *************************************************************************
* BrowserFragmentInterface.java
* **************************************************************************
* Copyright © 2015 VLC authors and VideoLAN
* Author: Geoffrey Métais
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
* ***************************************************************************
*/
package org.videolan.vlc.gui.tv.browser.interfaces;
public interface BrowserFragmentInterface {
void refresh();
void updateList();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment