Commit 7fe1f526 authored by Geoffrey Métais's avatar Geoffrey Métais

Audio player UI refactor

parent 871f0abe
......@@ -6,9 +6,15 @@
type="org.videolan.vlc.gui.audio.AudioPlayer" />
</data>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/content_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/background_default_darker" >
android:layout_height="match_parent" >
<ImageView
android:id="@+id/backgroundView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="?attr/background_default_darker"
android:scaleType="centerCrop"/>
<ProgressBar
android:id="@+id/progressBar"
......@@ -29,9 +35,9 @@
android:layout_height="60dip"
android:gravity="center_vertical"
android:orientation="horizontal"
android:background="?attr/background_default"
android:layout_below="@+id/progressBar"
android:fitsSystemWindows="true">
android:fitsSystemWindows="true"
android:background="?attr/background_default" >
<ImageButton
android:id="@+id/playlist_playasaudio_off"
......@@ -154,13 +160,13 @@
android:layout_centerHorizontal="true"
android:clipToPadding="false"
android:layout_gravity="center_horizontal"
android:background="?attr/background_default"
android:paddingBottom="@dimen/listview_bottom_padding" />
<org.videolan.vlc.gui.view.CoverMediaSwitcher
android:id="@+id/cover_media_switcher"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="@dimen/default_margin"
android:layout_centerHorizontal="true"
android:layout_below="@+id/header"
android:layout_above="@+id/player_controls"
......@@ -181,8 +187,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_alignParentBottom="true"
android:background="?attr/background_default">
android:layout_alignParentBottom="true">
<LinearLayout
android:layout_width="fill_parent"
......
<?xml version="1.0" encoding="utf-8"?>
<View xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/shadow_bottom"
android:layout_width="match_parent"
android:layout_height="6dp"
android:background="?attr/shadow_bottom_9patch"/>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<View xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/shadow_top"
android:layout_width="match_parent"
android:layout_height="6dp"
android:background="?attr/shadow_top_9patch"/>
\ No newline at end of file
......@@ -26,6 +26,7 @@
<attr name="list_title_last" format="reference|color" />
<attr name="list_title" format="reference|color" />
<attr name="color_menu_button" format="reference|color" />
<attr name="audio_player_background_tint" format="reference|color" />
<!--Main Icons-->
<attr name="ic_down_style" format="reference" />
......
......@@ -40,7 +40,7 @@
<color name="grey900transparent">#80212121</color>
<color name="blacktransparent">#b4000000</color>
<color name="whitetransparent">#dcffffff</color>
<color name="whitetransparent">#b4ffffff</color>
<color name="transparent">#00000000</color>
......
......@@ -33,6 +33,7 @@
<item name="background_player">@color/grey100</item>
<item name="background_header">@color/grey300</item>
<item name="background_audio_tips">@color/grey50transparent</item>
<item name="audio_player_background_tint">@color/whitetransparent</item>
<item name="audio_browser_separator">@color/orange500</item>
<item name="playlist_item_drag_shadow">@color/orange500</item>
<item name="audio_player_header_time">@color/orange500</item>
......@@ -125,6 +126,7 @@
<item name="background_player">@color/grey850</item>
<item name="background_header">@color/grey900</item>
<item name="background_audio_tips">@color/grey900transparent</item>
<item name="audio_player_background_tint">@color/grey900transparent</item>
<item name="audio_browser_separator">@color/orange500</item>
<item name="playlist_item_drag_shadow">@color/orange500</item>
<item name="audio_player_header_time">@color/orange500</item>
......
......@@ -1662,7 +1662,7 @@ public class PlaybackService extends MediaBrowserServiceCompat implements IVLCVo
@MainThread
public Bitmap getCover() {
if (hasCurrentMedia()) {
return AudioUtil.getCoverFromMemCache(PlaybackService.this, getCurrentMedia(), 512);
return AudioUtil.getCover(PlaybackService.this, getCurrentMedia(), 512);
}
return null;
}
......@@ -1670,7 +1670,7 @@ public class PlaybackService extends MediaBrowserServiceCompat implements IVLCVo
@MainThread
public Bitmap getCoverPrev() {
if (mPrevIndex != -1)
return AudioUtil.getCoverFromMemCache(PlaybackService.this, mMediaList.getMedia(mPrevIndex), 64);
return AudioUtil.getCover(PlaybackService.this, mMediaList.getMedia(mPrevIndex), 512);
else
return null;
}
......@@ -1678,7 +1678,7 @@ public class PlaybackService extends MediaBrowserServiceCompat implements IVLCVo
@MainThread
public Bitmap getCoverNext() {
if (mNextIndex != -1)
return AudioUtil.getCoverFromMemCache(PlaybackService.this, mMediaList.getMedia(mNextIndex), 64);
return AudioUtil.getCover(PlaybackService.this, mMediaList.getMedia(mNextIndex), 512);
else
return null;
}
......
......@@ -352,6 +352,10 @@ public class AudioPlayerContainerActivity extends AppCompatActivity implements P
return mAudioPlayer != null;
}
public boolean isAudioPlayerExpanded() {
return isAudioPlayerReady() && mBottomSheetBehavior.getState() == BottomSheetBehavior.STATE_EXPANDED;
}
private class AudioPlayerBottomSheetCallback extends BottomSheetBehavior.BottomSheetCallback {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
......
......@@ -21,11 +21,15 @@
package org.videolan.vlc.gui.audio;
import android.Manifest;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
......@@ -53,6 +57,7 @@ import android.widget.SeekBar.OnSeekBarChangeListener;
import org.videolan.libvlc.Media;
import org.videolan.libvlc.MediaPlayer;
import org.videolan.libvlc.util.AndroidUtil;
import org.videolan.medialibrary.Tools;
import org.videolan.medialibrary.media.MediaWrapper;
import org.videolan.vlc.PlaybackService;
......@@ -68,10 +73,12 @@ import org.videolan.vlc.gui.helpers.UiTools;
import org.videolan.vlc.gui.preferences.PreferencesActivity;
import org.videolan.vlc.gui.view.AudioMediaSwitcher.AudioMediaSwitcherListener;
import org.videolan.vlc.util.AndroidDevices;
import org.videolan.vlc.util.Strings;
public class AudioPlayer extends PlaybackServiceFragment implements PlaybackService.Callback, PlaylistAdapter.IPlayer, TextWatcher {
public static final String TAG = "VLC/AudioPlayer";
private static int DEFAULT_BACKGROUND_ID;
public static final int SEARCH_TIMEOUT_MILLIS = 5000;
private AudioPlayerBinding mBinding;
......@@ -102,6 +109,7 @@ public class AudioPlayer extends PlaybackServiceFragment implements PlaybackServ
@Override
public void onViewCreated(final View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
DEFAULT_BACKGROUND_ID = UiTools.getResourceFromAttribute(view.getContext(), R.attr.background_default_darker);
mPlaylistAdapter = new PlaylistAdapter(this);
mBinding.songsList.setLayoutManager(new LinearLayoutManager(mBinding.getRoot().getContext()));
mBinding.songsList.setAdapter(mPlaylistAdapter);
......@@ -177,7 +185,6 @@ public class AudioPlayer extends PlaybackServiceFragment implements PlaybackServ
public void doUpdate() {
if (mService == null || getActivity() == null)
return;
if (mService.hasMedia() && !mService.isVideoPlaying()) {
SharedPreferences mSettings= PreferenceManager.getDefaultSharedPreferences(getActivity());
//Check fragment resumed to not restore video on device turning off
......@@ -226,6 +233,7 @@ public class AudioPlayer extends PlaybackServiceFragment implements PlaybackServ
mBinding.shuffle.setVisibility(mService.canShuffle() ? View.VISIBLE : View.INVISIBLE);
mBinding.timeline.setOnSeekBarChangeListener(mTimelineListner);
updateList();
updateBackground();
}
@Override
......@@ -262,6 +270,37 @@ public class AudioPlayer extends PlaybackServiceFragment implements PlaybackServ
}
}
private void updateBackground() {
if (AndroidUtil.isJellyBeanMR1OrLater()) {
final MediaWrapper mw = mService.getCurrentMediaWrapper();
if (mw == null || TextUtils.isEmpty(mw.getArtworkMrl())) {
mBinding.backgroundView.setImageResource(DEFAULT_BACKGROUND_ID);
mBinding.backgroundView.clearColorFilter();
} else {
VLCApplication.runBackground(new Runnable() {
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
@Override
public void run() {
final Bitmap blurredCover = UiTools.blurBitmap(AudioUtil.readCoverBitmap(Strings.removeFileProtocole(Uri.decode(mw.getArtworkMrl())), mBinding.contentLayout.getWidth()));
if (blurredCover != null)
VLCApplication.runOnMainThread(new Runnable() {
@Override
public void run() {
if (((AudioPlayerContainerActivity)getActivity()).isAudioPlayerExpanded())
mBinding.header.setBackgroundResource(0);
mBinding.backgroundView.setColorFilter(UiTools.getColorFromAttribute(mBinding.backgroundView.getContext(), R.attr.audio_player_background_tint));
mBinding.backgroundView.setImageBitmap(blurredCover);
}
});
}
});
}
}
if (((AudioPlayerContainerActivity)getActivity()).isAudioPlayerExpanded())
setHeaderVisibilities(true, true, false, false, false, true);
}
public void updateList() {
hideSearchField();
if (mService != null)
......@@ -657,13 +696,17 @@ public class AudioPlayer extends PlaybackServiceFragment implements PlaybackServ
mPlayerState = newState;
switch (newState) {
case BottomSheetBehavior.STATE_COLLAPSED:
mBinding.header.setBackgroundResource(DEFAULT_BACKGROUND_ID);
setHeaderVisibilities(false, false, true, true, true, false);
break;
case BottomSheetBehavior.STATE_EXPANDED:
mBinding.header.setBackgroundResource(0);
setHeaderVisibilities(true, true, false, false, false, true);
showPlaylistTips();
mPlaylistAdapter.setCurrentIndex(mService.getCurrentMediaPosition());
break;
default:
mBinding.header.setBackgroundResource(0);
}
}
......
......@@ -28,13 +28,21 @@ import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.TypedArray;
import android.databinding.BindingAdapter;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.preference.PreferenceManager;
import android.renderscript.Allocation;
import android.renderscript.Element;
import android.renderscript.RenderScript;
import android.renderscript.ScriptIntrinsic;
import android.renderscript.ScriptIntrinsicBlur;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import android.support.design.widget.Snackbar;
import android.support.v4.app.FragmentActivity;
import android.support.v4.content.ContextCompat;
......@@ -263,4 +271,37 @@ public class UiTools {
return AsyncImageLoader.DEFAULT_COVER_AUDIO_DRAWABLE;
}
}
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1)
public static Bitmap blurBitmap(Bitmap bitmap){
//Let's create an empty bitmap with the same size of the bitmap we want to blur
Bitmap outBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
//Instantiate a new Renderscript
RenderScript rs = RenderScript.create(VLCApplication.getAppContext());
//Create an Intrinsic Blur Script using the Renderscript
ScriptIntrinsicBlur blurScript = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
//Create the Allocations (in/out) with the Renderscript and the in/out bitmaps
Allocation allIn = Allocation.createFromBitmap(rs, bitmap);
Allocation allOut = Allocation.createFromBitmap(rs, outBitmap);
//Set the radius of the blur
blurScript.setRadius(25.f);
//Perform the Renderscript
blurScript.setInput(allIn);
blurScript.forEach(allOut);
//Copy the final bitmap created by the out Allocation to the outBitmap
allOut.copyTo(outBitmap);
//After finishing everything, we destroy the Renderscript.
rs.destroy();
return outBitmap;
}
}
......@@ -168,7 +168,7 @@ public class AudioPlayerActivity extends BaseTvActivity implements PlaybackServi
MediaWrapper mw = mService.getCurrentMediaWrapper();
Bitmap cover = AudioUtil.getCover(this, mw, mCover.getWidth());
if (cover == null)
cover = mService.getCover();
cover = AudioUtil.getCover(this, mService.getCurrentMediaWrapper(), 512);
if (cover == null)
mCover.setImageResource(R.drawable.ic_tv_icon_big);
else
......
......@@ -26,6 +26,7 @@ import android.util.AttributeSet;
import android.view.LayoutInflater;
import org.videolan.vlc.PlaybackService;
import org.videolan.vlc.VLCApplication;
public abstract class AudioMediaSwitcher extends FlingViewGroup {
......@@ -41,37 +42,48 @@ public abstract class AudioMediaSwitcher extends FlingViewGroup {
setOnViewSwitchedListener(mViewSwitchListener);
}
public void updateMedia(PlaybackService service) {
removeAllViews();
hasPrevious = false;
previousPosition = 0;
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (service.hasPrevious()) {
addMediaView(inflater,
service.getTitlePrev(),
service.getArtistPrev(),
service.getCoverPrev());
hasPrevious = true;
}
if (service.hasMedia())
addMediaView(inflater,
service.getTitle(),
service.getArtist(),
service.getCover());
if (service.hasNext())
addMediaView(inflater,
service.getTitleNext(),
service.getArtistNext(),
service.getCoverNext());
if (service.hasPrevious() && service.hasMedia()) {
previousPosition = 1;
scrollTo(1);
}
else
scrollTo(0);
public void updateMedia(final PlaybackService service) {
VLCApplication.runBackground(new Runnable() {
@Override
public void run() {
final Bitmap coverPrev = service.getCoverPrev(), coverCurrent = service.getCover(), coverNext = service.getCoverNext();
VLCApplication.runOnMainThread(new Runnable() {
@Override
public void run() {
removeAllViews();
hasPrevious = false;
previousPosition = 0;
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (service.hasPrevious()) {
addMediaView(inflater,
service.getTitlePrev(),
service.getArtistPrev(),
coverPrev);
hasPrevious = true;
}
if (service.hasMedia())
addMediaView(inflater,
service.getTitle(),
service.getArtist(),
coverCurrent);
if (service.hasNext())
addMediaView(inflater,
service.getTitleNext(),
service.getArtistNext(),
coverNext);
if (service.hasPrevious() && service.hasMedia()) {
previousPosition = 1;
scrollTo(1);
}
else
scrollTo(0);
}
});
}
});
}
protected abstract void addMediaView(LayoutInflater inflater, String title, String artist, Bitmap cover);
......
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