Commit 2afaafa6 authored by Geoffrey Métais's avatar Geoffrey Métais
Browse files

TV: Improve audio player activity

parent 9970c1d3
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Define the background properties like color etc -->
<item
android:id="@android:id/background"
android:height="@dimen/half_default_margin"
android:gravity="center"
android:start="2dp"
android:end="2dp">
<shape>
<solid android:color="@color/grey700" />
</shape>
</item>
<!-- Define the progress properties like start color, end color etc -->
<item
android:id="@android:id/progress"
android:height="@dimen/half_default_margin"
android:gravity="center"
android:start="2dp"
android:end="2dp">
android:gravity="center">
<clip>
<shape>
<solid android:color="@color/orange500" />
......
......@@ -111,7 +111,6 @@
android:clickable="true"
android:focusable="true"
android:nextFocusDown="@+id/playlist"
android:nextFocusUp="@+id/media_progress"
android:onClick="onClick"
android:src="@drawable/ic_repeat_w"
tools:src="@drawable/ic_repeat" />
......@@ -127,7 +126,6 @@
android:clickable="true"
android:focusable="true"
android:nextFocusDown="@+id/playlist"
android:nextFocusUp="@+id/media_progress"
android:onClick="onClick"
android:src="@drawable/ic_previous_w"
tools:src="@drawable/ic_previous" />
......@@ -143,7 +141,6 @@
android:clickable="true"
android:focusable="true"
android:nextFocusDown="@+id/playlist"
android:nextFocusUp="@+id/media_progress"
android:onClick="onClick"
android:src="@drawable/ic_play_w"
tools:src="@drawable/ic_play" >
......@@ -161,7 +158,6 @@
android:clickable="true"
android:focusable="true"
android:nextFocusDown="@+id/playlist"
android:nextFocusUp="@+id/media_progress"
android:onClick="onClick"
android:src="@drawable/ic_next_w"
tools:src="@drawable/ic_next" />
......@@ -176,9 +172,8 @@
app:layout_constraintBottom_toBottomOf="parent"
android:clickable="true"
android:focusable="true"
android:nextFocusDown="@+id/playlist"
android:nextFocusDown="@+id/button_shuffle"
android:nextFocusRight="@id/playlist"
android:nextFocusUp="@+id/media_progress"
android:onClick="onClick"
android:src="@drawable/ic_shuffle_w"
tools:src="@drawable/ic_shuffle" />
......@@ -192,13 +187,10 @@
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="@+id/background"
app:layout_constraintLeft_toRightOf="@+id/album_cover"
android:focusable="true"
android:nextFocusLeft="@+id/button_play"
android:nextFocusUp="@+id/playlist"
android:nextFocusLeft="@+id/button_shuffle"
android:nextFocusRight="@+id/button_play"
android:nextFocusRight="@+id/playlist"
android:nextFocusDown="@+id/playlist"
android:scrollbars="vertical"
android:descendantFocusability="beforeDescendants"
android:layout_margin="@dimen/half_default_margin" />
</android.support.constraint.ConstraintLayout>
</layout>
<?xml version="1.0" encoding="utf-8"?>
<layout>
<data>
<import type="org.videolan.vlc.media.MediaUtils" />
<variable
name="bgColor"
type="int" />
<variable
name="media"
type="org.videolan.medialibrary.media.MediaWrapper" />
</data>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:padding="@dimen/half_default_margin"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/activatedBackgroundIndicator"
android:minHeight="?android:attr/listPreferredItemHeight"
android:orientation="vertical">
android:focusable="true"
android:clickable="true"
android:orientation="vertical"
android:background="@{bgColor}">
<TextView android:id="@android:id/text1"
<TextView android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="text1"
android:textSize="20sp"
android:textStyle="bold"
android:textColor="@color/grey50"/>
android:text="@{MediaUtils.getMediaTitle(media)}"
android:textColor="@color/grey50" />
<TextView android:id="@android:id/text2"
<TextView android:id="@+id/artist"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="text2"
android:textSize="16sp"
android:textColor="@color/grey50"/>
android:text="@{MediaUtils.getMediaArtist(context, media)}"
android:textColor="@color/grey50" />
</LinearLayout>
\ No newline at end of file
</LinearLayout>
</layout>
\ No newline at end of file
......@@ -60,7 +60,7 @@ import java.util.List;
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
public class AudioPlayerActivity extends BaseTvActivity implements PlaybackService.Client.Callback,
PlaybackService.Callback, View.OnFocusChangeListener {
PlaybackService.Callback {
public static final String TAG = "VLC/AudioPlayerActivity";
public static final String MEDIA_LIST = "media_list";
......@@ -68,13 +68,12 @@ public class AudioPlayerActivity extends BaseTvActivity implements PlaybackServi
private TvAudioPlayerBinding mBinding;
private PlaylistAdapter mAdapter;
private LinearLayoutManager mLayoutManager;
private List<MediaWrapper> mMediaList;
//PAD navigation
private static final int JOYSTICK_INPUT_DELAY = 300;
private long mLastMove;
private int mCurrentlyPlaying, mPositionSaved = 0;
private int mCurrentlyPlaying;
private boolean mShuffling = false;
private String mCurrentCoverArt;
......@@ -84,13 +83,10 @@ public class AudioPlayerActivity extends BaseTvActivity implements PlaybackServi
mBinding.setProgress(new Progress());
mMediaList = getIntent().getParcelableArrayListExtra(MEDIA_LIST);
if (mMediaList == null) mMediaList = new ArrayList<>();
mCurrentlyPlaying = getIntent().getIntExtra(MEDIA_POSITION, 0);
mLayoutManager = new LinearLayoutManager(this);
mBinding.playlist.setLayoutManager(mLayoutManager);
mBinding.playlist.setLayoutManager(new LinearLayoutManager(this));
mBinding.playlist.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
mBinding.playlist.setOnFocusChangeListener(this);
if (mMediaList == null)
mMediaList = new ArrayList<>();
mAdapter = new PlaylistAdapter(this, mMediaList);
mBinding.playlist.setAdapter(mAdapter);
}
......@@ -98,8 +94,7 @@ public class AudioPlayerActivity extends BaseTvActivity implements PlaybackServi
@Override
protected void onStop() {
/* unregister before super.onStop() since mService is set to null from this call */
if (mService != null)
mService.removeCallback(this);
if (mService != null) mService.removeCallback(this);
super.onStop();
}
......@@ -108,7 +103,7 @@ public class AudioPlayerActivity extends BaseTvActivity implements PlaybackServi
super.onConnected(service);
mService.addCallback(this);
List<MediaWrapper> medias = mService.getMedias();
final List<MediaWrapper> medias = mService.getMedias();
if (!mMediaList.isEmpty() && !mMediaList.equals(medias)) {
mService.load(mMediaList, mCurrentlyPlaying);
} else {
......@@ -116,8 +111,7 @@ public class AudioPlayerActivity extends BaseTvActivity implements PlaybackServi
if (mCurrentlyPlaying != mService.getCurrentMediaPosition())
mService.playIndex(mCurrentlyPlaying);
update();
mAdapter = new PlaylistAdapter(this, mMediaList);
mBinding.playlist.setAdapter(mAdapter);
mAdapter.updateList(mMediaList);
}
}
......@@ -134,10 +128,9 @@ public class AudioPlayerActivity extends BaseTvActivity implements PlaybackServi
@Override
public void update() {
if (mService == null || !mService.hasMedia())
return;
if (mService == null || !mService.hasMedia()) return;
mBinding.buttonPlay.setImageResource(mService.isPlaying() ? R.drawable.ic_pause_w : R.drawable.ic_play_w);
SharedPreferences mSettings= PreferenceManager.getDefaultSharedPreferences(this);
final SharedPreferences mSettings= PreferenceManager.getDefaultSharedPreferences(this);
if (mSettings.getBoolean(PreferencesActivity.VIDEO_RESTORE, false)) {
mSettings.edit().putBoolean(PreferencesActivity.VIDEO_RESTORE, false).apply();
mService.getCurrentMediaWrapper().removeFlags(MediaWrapper.MEDIA_FORCE_AUDIO);
......@@ -149,10 +142,9 @@ public class AudioPlayerActivity extends BaseTvActivity implements PlaybackServi
mBinding.mediaArtist.setText(mService.getArtist());
mBinding.getProgress().update(mService.getTime(), mService.getLength());
mCurrentlyPlaying = mService.getCurrentMediaPosition();
selectItem(mCurrentlyPlaying);
mAdapter.setSelection(mCurrentlyPlaying);
final MediaWrapper mw = mService.getCurrentMediaWrapper();
if (TextUtils.equals(mCurrentCoverArt, mw.getArtworkMrl()))
return;
if (TextUtils.equals(mCurrentCoverArt, mw.getArtworkMrl())) return;
mCurrentCoverArt = mw.getArtworkMrl();
updateBackground();
}
......@@ -183,8 +175,7 @@ public class AudioPlayerActivity extends BaseTvActivity implements PlaybackServi
@Override
public void updateProgress() {
if (mService != null)
mBinding.getProgress().updateTime(mService.getTime());
if (mService != null) mBinding.getProgress().updateTime(mService.getTime());
}
@Override
......@@ -233,37 +224,15 @@ public class AudioPlayerActivity extends BaseTvActivity implements PlaybackServi
case KeyEvent.KEYCODE_BUTTON_L1:
goPrevious();
return true;
/*
* Playlist navigation
*/
case KeyEvent.KEYCODE_DPAD_UP:
if (mBinding.playlist.hasFocus()) {
selectPrevious();
return true;
} else
return false;
case KeyEvent.KEYCODE_DPAD_DOWN:
if (mBinding.playlist.hasFocus()) {
selectNext();
return true;
} else
return false;
case KeyEvent.KEYCODE_DPAD_CENTER:
if (mBinding.playlist.hasFocus()) {
playSelection();
return true;
} else
return false;
default:
return super.onKeyDown(keyCode, event);
}
}
public void playSelection() {
if (mService == null)
return;
mService.playIndex(mAdapter.getmSelectedItem());
mCurrentlyPlaying = mAdapter.getmSelectedItem();
if (mService == null) return;
mService.playIndex(mAdapter.getSelectedItem());
mCurrentlyPlaying = mAdapter.getSelectedItem();
}
public boolean dispatchGenericMotionEvent(MotionEvent event){
......@@ -273,32 +242,27 @@ public class AudioPlayerActivity extends BaseTvActivity implements PlaybackServi
event.getAction() != MotionEvent.ACTION_MOVE)
return false;
InputDevice inputDevice = event.getDevice();
final InputDevice inputDevice = event.getDevice();
float dpadx = event.getAxisValue(MotionEvent.AXIS_HAT_X);
float dpady = event.getAxisValue(MotionEvent.AXIS_HAT_Y);
if (inputDevice == null || Math.abs(dpadx) == 1.0f || Math.abs(dpady) == 1.0f)
return false;
if (inputDevice == null || Math.abs(dpadx) == 1.0f || Math.abs(dpady) == 1.0f) return false;
float x = AndroidDevices.getCenteredAxis(event, inputDevice,
MotionEvent.AXIS_X);
if (System.currentTimeMillis() - mLastMove > JOYSTICK_INPUT_DELAY){
if (Math.abs(x) > 0.3){
seek(x > 0.0f ? 10000 : -10000);
mLastMove = System.currentTimeMillis();
return true;
}
if (Math.abs(x) > 0.3 && System.currentTimeMillis() - mLastMove > JOYSTICK_INPUT_DELAY) {
seek(x > 0.0f ? 10000 : -10000);
mLastMove = System.currentTimeMillis();
return true;
}
return true;
}
private void seek(int delta) {
if (mService == null)
return;
if (mService == null) return;
int time = (int) mService.getTime()+delta;
if (time < 0 || time > mService.getLength())
return;
if (time < 0 || time > mService.getLength()) return;
mService.setTime(time);
}
......@@ -323,24 +287,20 @@ public class AudioPlayerActivity extends BaseTvActivity implements PlaybackServi
}
private void setShuffleMode(boolean shuffle) {
if (mService == null)
return;
if (mService == null) return;
mShuffling = shuffle;
mBinding.buttonShuffle.setImageResource(shuffle ? R.drawable.ic_shuffle_on :
R.drawable.ic_shuffle_w);
List<MediaWrapper> medias = mService.getMedias();
if (shuffle)
Collections.shuffle(medias);
else
Collections.sort(medias, MediaComparators.byTrackNumber);
final List<MediaWrapper> medias = mService.getMedias();
if (shuffle) Collections.shuffle(medias);
else Collections.sort(medias, MediaComparators.byTrackNumber);
mService.load(medias, 0);
mAdapter.updateList(medias);
update();
}
private void updateRepeatMode() {
if (mService == null)
return;
if (mService == null) return;
int type = mService.getRepeatType();
if (type == Constants.REPEAT_NONE){
mService.setRepeatType(Constants.REPEAT_ALL);
......@@ -355,69 +315,17 @@ public class AudioPlayerActivity extends BaseTvActivity implements PlaybackServi
}
private void goPrevious() {
if (mService != null && mService.hasPrevious()) {
mService.previous(false);
}
if (mService != null && mService.hasPrevious()) mService.previous(false);
}
private void goNext() {
if (mService != null && mService.hasNext()){
mService.next();
}
if (mService != null && mService.hasNext()) mService.next();
}
private void togglePlayPause() {
if (mService == null)
return;
if (mService.isPlaying())
mService.pause();
else if (mService.hasMedia())
mService.play();
}
private void selectNext() {
if (mAdapter.getmSelectedItem() >= mAdapter.getItemCount()-1) {
mBinding.mediaProgress.requestFocus();
selectItem(-1);
return;
}
selectItem(mAdapter.getmSelectedItem()+1);
}
private void selectPrevious() {
if (mAdapter.getmSelectedItem() < 1){
mBinding.buttonPlay.requestFocus();
selectItem(-1);
return;
}
selectItem(mAdapter.getmSelectedItem()-1);
}
private void selectItem(final int position) {
if (position >= mMediaList.size())
return;
mBinding.playlist.post(new Runnable() {
@Override
public void run() {
if (position != -1 && (position > mLayoutManager.findLastCompletelyVisibleItemPosition()
|| position < mLayoutManager.findFirstCompletelyVisibleItemPosition())) {
mBinding.playlist.stopScroll();
mBinding.playlist.smoothScrollToPosition(position);
}
mAdapter.setSelection(position);
}
});
}
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus)
selectItem(mPositionSaved);
else {
if (mAdapter.getmSelectedItem() != -1)
mPositionSaved = mAdapter.getmSelectedItem();
selectItem(-1);
}
if (mService == null) return;
if (mService.isPlaying()) mService.pause();
else if (mService.hasMedia()) mService.play();
}
public class Progress {
......
......@@ -24,86 +24,82 @@ import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import org.videolan.medialibrary.media.MediaWrapper;
import org.videolan.vlc.R;
import org.videolan.vlc.media.MediaUtils;
import org.videolan.vlc.databinding.TvSimpleListItemBinding;
import org.videolan.vlc.gui.helpers.SelectorViewHolder;
import org.videolan.vlc.util.Util;
import java.util.List;
public class PlaylistAdapter extends RecyclerView.Adapter<PlaylistAdapter.ViewHolder> implements View.OnClickListener{
public class PlaylistAdapter extends RecyclerView.Adapter<PlaylistAdapter.ViewHolder> {
public static final String TAG = "VLC/PlaylistAdapter";
private AudioPlayerActivity mAudioPlayerActivity;
private List<MediaWrapper> mDataset;
private int mSelectedItem = -1;
private AudioPlayerActivity audioPlayerActivity;
private List<MediaWrapper> dataset;
private int selectedItem = -1;
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView mTitleTv;
public TextView mArtistTv;
public ViewHolder(View v) {
super(v);
mTitleTv = (TextView) v.findViewById(android.R.id.text1);
mArtistTv = (TextView) v.findViewById(android.R.id.text2);
public class ViewHolder extends SelectorViewHolder<TvSimpleListItemBinding> implements View.OnClickListener {
public ViewHolder(TvSimpleListItemBinding vdb) {
super(vdb);
itemView.setOnClickListener(this);
}
@Override
public void onClick(View v) {
setSelection(getLayoutPosition());
audioPlayerActivity.playSelection();
}
}
public PlaylistAdapter(AudioPlayerActivity audioPlayerActivity, List<MediaWrapper> myDataset) {
mDataset = myDataset;
mAudioPlayerActivity = audioPlayerActivity;
PlaylistAdapter(AudioPlayerActivity audioPlayerActivity, List<MediaWrapper> myDataset) {
dataset = myDataset;
this.audioPlayerActivity = audioPlayerActivity;
}
@Override
public PlaylistAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.tv_simple_list_item, parent, false);
v.setClickable(true);
v.setFocusable(true);
v.setFocusableInTouchMode(true);
ViewHolder vh = new ViewHolder(v);
return vh;
public PlaylistAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ViewHolder(TvSimpleListItemBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false));
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
MediaWrapper mediaWrapper = mDataset.get(position);
holder.mTitleTv.setText(MediaUtils.getMediaTitle(mediaWrapper));
holder.mArtistTv.setText(MediaUtils.getMediaArtist(holder.itemView.getContext(), mediaWrapper));
holder.itemView.setActivated(position == mSelectedItem);
holder.itemView.setOnClickListener(this);
holder.binding.setMedia(dataset.get(position));
final int textAppearance = position == selectedItem ? R.style.TextAppearance_AppCompat_Title : R.style.TextAppearance_AppCompat_Medium;
holder.binding.artist.setTextAppearance(textAppearance);
holder.binding.title.setTextAppearance(textAppearance);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position, List<Object> payloads) {
if (Util.isListEmpty(payloads)) super.onBindViewHolder(holder, position, payloads);
else {
final int textAppearance = (boolean) payloads.get(0) ? R.style.TextAppearance_AppCompat_Title : R.style.TextAppearance_AppCompat_Medium;
holder.binding.artist.setTextAppearance(textAppearance);
holder.binding.title.setTextAppearance(textAppearance);
}
}
@Override
public int getItemCount() {
return mDataset.size();
return dataset.size();
}
public int getmSelectedItem(){
return mSelectedItem;
int getSelectedItem(){
return selectedItem;
}
public void setSelection(int pos) {
if (pos == mSelectedItem)
return;
int previous = mSelectedItem;
mSelectedItem = pos;
if (previous != -1)
notifyItemChanged(previous);
if (pos != -1){
notifyItemChanged(mSelectedItem);
}
if (pos == selectedItem) return;
int previous = selectedItem;
selectedItem = pos;
if (previous != -1) notifyItemChanged(previous, false);
if (pos != -1) notifyItemChanged(selectedItem, true);
}
public void updateList(List<MediaWrapper> list){
mDataset = list;
dataset = list;
notifyDataSetChanged();
}
@Override
public void onClick(View v){
mAudioPlayerActivity.playSelection();
}
}
\ No newline at end of file
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