mirror of
https://github.com/yuliskov/SmartTube.git
synced 2025-05-17 11:25:54 +08:00
video card: playback preview: upd
This commit is contained in:
@ -114,6 +114,10 @@ public class PlayerUIController extends BasePlayerController {
|
||||
disableUiAutoHideTimeout();
|
||||
disableSuggestionsResetTimeout();
|
||||
|
||||
if (getPlayer() == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean isHandled = handleBackKey(keyCode) || handleMenuKey(keyCode) ||
|
||||
handleConfirmKey(keyCode) || handleStopKey(keyCode) || handleNumKeys(keyCode) ||
|
||||
handlePlayPauseKey(keyCode) || handleLeftRightSkip(keyCode);
|
||||
@ -600,10 +604,6 @@ public class PlayerUIController extends BasePlayerController {
|
||||
}
|
||||
|
||||
private boolean handleMenuKey(int keyCode) {
|
||||
if (getPlayer() == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean controlsShown = getPlayer().isOverlayShown();
|
||||
boolean suggestionsShown = getPlayer().isSuggestionsShown();
|
||||
|
||||
@ -619,10 +619,6 @@ public class PlayerUIController extends BasePlayerController {
|
||||
}
|
||||
|
||||
private boolean handleConfirmKey(int keyCode) {
|
||||
if (getPlayer() == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean controlsShown = getPlayer().isOverlayShown();
|
||||
|
||||
if (KeyHelpers.isConfirmKey(keyCode) && !controlsShown) {
|
||||
|
@ -119,6 +119,10 @@ public class VideoStateController extends BasePlayerController {
|
||||
|
||||
@Override
|
||||
public void onEngineReleased() {
|
||||
if (getPlayer() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Save previous state
|
||||
if (getPlayer().containsMedia()) {
|
||||
setPlayEnabled(getPlayer().getPlayWhenReady());
|
||||
|
@ -23,7 +23,6 @@ import com.liskovsoft.smartyoutubetv2.common.app.models.data.Video;
|
||||
import com.liskovsoft.smartyoutubetv2.common.app.models.playback.listener.PlayerEventListener;
|
||||
import com.liskovsoft.smartyoutubetv2.common.exoplayer.ExoMediaSourceFactory;
|
||||
import com.liskovsoft.smartyoutubetv2.common.exoplayer.errors.TrackErrorFixer;
|
||||
import com.liskovsoft.smartyoutubetv2.common.exoplayer.other.ExoPlayerInitializer;
|
||||
import com.liskovsoft.smartyoutubetv2.common.exoplayer.other.VolumeBooster;
|
||||
import com.liskovsoft.smartyoutubetv2.common.exoplayer.selector.ExoFormatItem;
|
||||
import com.liskovsoft.smartyoutubetv2.common.exoplayer.selector.FormatItem;
|
||||
@ -53,6 +52,7 @@ public class ExoPlayerController implements Player.EventListener, PlayerControll
|
||||
private PlayerView mPlayerView;
|
||||
private VolumeBooster mVolumeBooster;
|
||||
private boolean mIsEnded;
|
||||
private Runnable mOnVideoLoaded;
|
||||
|
||||
public ExoPlayerController(Context context, PlayerEventListener eventListener) {
|
||||
PlayerTweaksData playerTweaksData = PlayerTweaksData.instance(context);
|
||||
@ -301,14 +301,15 @@ public class ExoPlayerController implements Player.EventListener, PlayerControll
|
||||
}
|
||||
|
||||
private void notifyOnVideoLoad() {
|
||||
if (mVideo == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mOnSourceChanged) {
|
||||
mOnSourceChanged = false;
|
||||
|
||||
mEventListener.onVideoLoaded(mVideo);
|
||||
|
||||
if (mOnVideoLoaded != null) {
|
||||
mOnVideoLoaded.run();
|
||||
}
|
||||
|
||||
// Produce thread sync problems
|
||||
// Attempt to read from field 'java.util.TreeMap$Node java.util.TreeMap$Node.left' on a null object reference
|
||||
//mTrackSelectorManager.fixTracksSelection();
|
||||
@ -440,6 +441,11 @@ public class ExoPlayerController implements Player.EventListener, PlayerControll
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnVideoLoaded(Runnable onVideoLoaded) {
|
||||
mOnVideoLoaded = onVideoLoaded;
|
||||
}
|
||||
|
||||
private void setQualityInfo(String qualityInfoStr) {
|
||||
if (mPlayerView != null && qualityInfoStr != null) {
|
||||
mPlayerView.setQualityInfo(qualityInfoStr);
|
||||
|
@ -43,4 +43,5 @@ public interface PlayerController {
|
||||
void setVolume(float volume);
|
||||
float getVolume();
|
||||
void resetPlayerState();
|
||||
void setOnVideoLoaded(Runnable onVideoLoaded);
|
||||
}
|
||||
|
@ -133,7 +133,7 @@ public class VideoCardPresenter extends LongClickPresenter {
|
||||
|
||||
if (mIsAnimatedPreviewsEnabled) {
|
||||
cardView.setPreviewUrl(video.previewUrl);
|
||||
//cardView.setPreviewVideoId(video.videoId);
|
||||
cardView.setPreviewVideoId(video.videoId);
|
||||
}
|
||||
|
||||
cardView.setMainImageDimensions(mWidth, mHeight);
|
||||
@ -170,6 +170,9 @@ public class VideoCardPresenter extends LongClickPresenter {
|
||||
// Remove references to images so that the garbage collector can free up memory.
|
||||
cardView.setBadgeImage(null);
|
||||
cardView.setMainImage(null);
|
||||
|
||||
// Cleanup Glide resources. https://chatgpt.com/share/682120c5-e428-8010-b848-371b2dec0cd5
|
||||
Glide.with(cardView.getContext()).clear(cardView.getMainImageView());
|
||||
}
|
||||
|
||||
private void updateDimensions(Context context) {
|
||||
|
@ -4,13 +4,15 @@ import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ImageView.ScaleType;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||
import com.liskovsoft.smartyoutubetv2.common.utils.Utils;
|
||||
import com.liskovsoft.smartyoutubetv2.tv.R;
|
||||
import com.liskovsoft.smartyoutubetv2.tv.ui.widgets.embedplayer.EmbedPlayerView;
|
||||
import com.liskovsoft.smartyoutubetv2.tv.util.ViewUtil;
|
||||
@ -19,11 +21,15 @@ public class ComplexImageView extends RelativeLayout {
|
||||
private ImageView mMainImage;
|
||||
private ImageView mPreviewImage;
|
||||
private EmbedPlayerView mPreviewPlayer;
|
||||
private FrameLayout mPreviewContainer;
|
||||
private ProgressBar mProgressBar;
|
||||
private TextView mBadgeText;
|
||||
private String mPreviewUrl;
|
||||
private String mPreviewVideoId;
|
||||
private ViewGroup mProgressContainer;
|
||||
private int mPreviewWidth;
|
||||
private int mPreviewHeight;
|
||||
private Runnable mCreateAndStartPlayer;
|
||||
|
||||
public ComplexImageView(Context context) {
|
||||
super(context);
|
||||
@ -43,11 +49,10 @@ public class ComplexImageView extends RelativeLayout {
|
||||
private void init() {
|
||||
inflate(getContext(), R.layout.text_badge_image_view, this);
|
||||
mMainImage = findViewById(R.id.main_image);
|
||||
mPreviewImage = findViewById(R.id.preview_image);
|
||||
mPreviewPlayer = findViewById(R.id.preview_player);
|
||||
mBadgeText = findViewById(R.id.extra_text_badge);
|
||||
mProgressBar = findViewById(R.id.clip_progress);
|
||||
mProgressContainer = findViewById(R.id.clip_info);
|
||||
mPreviewContainer = findViewById(R.id.preview_container);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -108,49 +113,52 @@ public class ComplexImageView extends RelativeLayout {
|
||||
mPreviewVideoId = videoId;
|
||||
}
|
||||
|
||||
//public void startPlayback() {
|
||||
// if (mPreviewUrl == null) {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// mPreviewImage.setVisibility(View.VISIBLE);
|
||||
//
|
||||
// Glide.with(getContext().getApplicationContext()) // FIX: "You cannot start a load for a destroyed activity"
|
||||
// .load(mPreviewUrl)
|
||||
// .apply(ViewUtil.glideOptions())
|
||||
// .into(mPreviewImage);
|
||||
//}
|
||||
//
|
||||
//public void stopPlayback() {
|
||||
// if (mPreviewUrl == null) {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// mPreviewImage.setVisibility(View.GONE);
|
||||
// mPreviewImage.setImageDrawable(null);
|
||||
//}
|
||||
|
||||
public void startPlayback() {
|
||||
if (mPreviewUrl != null) {
|
||||
mPreviewImage.setVisibility(View.VISIBLE);
|
||||
if (mPreviewImage == null) {
|
||||
mPreviewImage = new ImageView(getContext());
|
||||
mPreviewImage.setScaleType(ScaleType.CENTER_CROP);
|
||||
mPreviewImage.setAdjustViewBounds(true);
|
||||
mPreviewContainer.addView(mPreviewImage, new FrameLayout.LayoutParams(mPreviewWidth, mPreviewHeight));
|
||||
}
|
||||
|
||||
Glide.with(getContext().getApplicationContext()) // FIX: "You cannot start a load for a destroyed activity"
|
||||
.load(mPreviewUrl)
|
||||
.apply(ViewUtil.glideOptions())
|
||||
.into(mPreviewImage);
|
||||
} else if (mPreviewVideoId != null) {
|
||||
mPreviewPlayer.setVisibility(View.VISIBLE);
|
||||
mPreviewPlayer.openVideo(mPreviewVideoId);
|
||||
if (mCreateAndStartPlayer == null) {
|
||||
mCreateAndStartPlayer = this::createAndStartPlayer;
|
||||
}
|
||||
|
||||
Utils.postDelayed(mCreateAndStartPlayer, 3_000);
|
||||
}
|
||||
}
|
||||
|
||||
private void createAndStartPlayer() {
|
||||
if (mPreviewPlayer == null) {
|
||||
mPreviewPlayer = new EmbedPlayerView(getContext());
|
||||
mPreviewPlayer.setUseController(false);
|
||||
mPreviewPlayer.setOnLoad(() -> mPreviewContainer.addView(mPreviewPlayer, new FrameLayout.LayoutParams(mPreviewWidth, mPreviewHeight)));
|
||||
}
|
||||
|
||||
mPreviewPlayer.openVideo(mPreviewVideoId);
|
||||
}
|
||||
|
||||
public void stopPlayback() {
|
||||
if (mPreviewUrl != null) {
|
||||
mPreviewImage.setVisibility(View.GONE);
|
||||
mPreviewContainer.removeView(mPreviewImage);
|
||||
mPreviewImage.setImageDrawable(null);
|
||||
Glide.with(getContext()).clear(mPreviewImage);
|
||||
mPreviewImage = null;
|
||||
} else if (mPreviewVideoId != null) {
|
||||
mPreviewPlayer.setVisibility(View.GONE);
|
||||
mPreviewPlayer.finish(); // TODO: not implemented
|
||||
Utils.removeCallbacks(mCreateAndStartPlayer);
|
||||
|
||||
if (mPreviewPlayer != null) {
|
||||
mPreviewContainer.removeView(mPreviewPlayer);
|
||||
mPreviewPlayer.finish();
|
||||
mPreviewPlayer = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -178,9 +186,11 @@ public class ComplexImageView extends RelativeLayout {
|
||||
}
|
||||
|
||||
private void setPreviewDimensions(int width, int height) {
|
||||
ViewGroup.LayoutParams lp = mPreviewImage.getLayoutParams();
|
||||
lp.width = width;
|
||||
lp.height = height;
|
||||
mPreviewImage.setLayoutParams(lp);
|
||||
mPreviewWidth = width;
|
||||
mPreviewHeight = height;
|
||||
//ViewGroup.LayoutParams lp = mPreviewImage.getLayoutParams();
|
||||
//lp.width = width;
|
||||
//lp.height = height;
|
||||
//mPreviewImage.setLayoutParams(lp);
|
||||
}
|
||||
}
|
||||
|
@ -36,6 +36,8 @@ public class EmbedPlayerView extends PlayerView implements PlaybackView {
|
||||
private ExoPlayerInitializer mPlayerInitializer;
|
||||
private PlayerController mExoPlayerController;
|
||||
private PlaybackPresenter mPlaybackPresenter;
|
||||
private Video mVideo;
|
||||
private Runnable mOnLoad;
|
||||
|
||||
public EmbedPlayerView(Context context) {
|
||||
super(context);
|
||||
@ -216,12 +218,16 @@ public class EmbedPlayerView extends PlayerView implements PlaybackView {
|
||||
|
||||
@Override
|
||||
public void setVideo(Video item) {
|
||||
mVideo = item;
|
||||
|
||||
if (mExoPlayerController != null) {
|
||||
mExoPlayerController.setVideo(mVideo);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Video getVideo() {
|
||||
return null;
|
||||
return mVideo;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -448,17 +454,28 @@ public class EmbedPlayerView extends PlayerView implements PlaybackView {
|
||||
}
|
||||
|
||||
public void openVideo(Video video) {
|
||||
initPlayer();
|
||||
if (mPlaybackPresenter == null) {
|
||||
mPlaybackPresenter = PlaybackPresenter.instance(getContext());
|
||||
}
|
||||
|
||||
// Fullscreen playback is running. Skipping
|
||||
if (mPlaybackPresenter.getView() != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
mVideo = video;
|
||||
mPlaybackPresenter.onNewVideo(video);
|
||||
initPlayer();
|
||||
}
|
||||
|
||||
private void createPlayer() {
|
||||
private void createPlayerObjects() {
|
||||
// Use default or pass your bandwidthMeter here: bandwidthMeter = new DefaultBandwidthMeter.Builder(getContext()).build()
|
||||
DefaultTrackSelector trackSelector = new RestoreTrackSelector(new AdaptiveTrackSelection.Factory());
|
||||
mExoPlayerController.setTrackSelector(trackSelector);
|
||||
|
||||
DefaultRenderersFactory renderersFactory = new CustomOverridesRenderersFactory(getContext());
|
||||
mPlayer = mPlayerInitializer.createPlayer(getContext(), renderersFactory, trackSelector);
|
||||
mPlayer.setPlayWhenReady(true);
|
||||
|
||||
// Fix seeking on TextureView (some devices only)
|
||||
if (PlayerTweaksData.instance(getContext()).isTextureViewEnabled()) {
|
||||
@ -467,6 +484,7 @@ public class EmbedPlayerView extends PlayerView implements PlaybackView {
|
||||
}
|
||||
|
||||
mExoPlayerController.setPlayer(mPlayer);
|
||||
mExoPlayerController.setVideo(mVideo);
|
||||
|
||||
if (PlayerTweaksData.instance(getContext()).isAudioFocusEnabled()) {
|
||||
ExoPlayerInitializer.enableAudioFocus(mPlayer, true);
|
||||
@ -476,8 +494,9 @@ public class EmbedPlayerView extends PlayerView implements PlaybackView {
|
||||
}
|
||||
|
||||
private void releasePlayer() {
|
||||
if (mPlayer != null) {
|
||||
if (isEngineInitialized()) {
|
||||
Log.d(TAG, "releasePlayer: Start releasing player engine...");
|
||||
mOnLoad = null;
|
||||
mPlaybackPresenter.onEngineReleased();
|
||||
destroyPlayerObjects();
|
||||
}
|
||||
@ -488,19 +507,31 @@ public class EmbedPlayerView extends PlayerView implements PlaybackView {
|
||||
mExoPlayerController.release();
|
||||
mPlayer = null;
|
||||
setPlayer(null);
|
||||
mPlaybackPresenter.setView(null);
|
||||
//mPlaybackPresenter.setView(null);
|
||||
}
|
||||
|
||||
private void initPlayer() {
|
||||
if (mPlayer != null) {
|
||||
if (isEngineInitialized()) {
|
||||
return;
|
||||
}
|
||||
|
||||
mPlayerInitializer = new ExoPlayerInitializer(getContext());
|
||||
mPlaybackPresenter = PlaybackPresenter.instance(getContext());
|
||||
mPlaybackPresenter.setView(this);
|
||||
mExoPlayerController = new ExoPlayerController(getContext(), mPlaybackPresenter);
|
||||
mPlaybackPresenter.onViewInitialized();
|
||||
createPlayer();
|
||||
mExoPlayerController.setOnVideoLoaded(this::onVideoLoaded);
|
||||
mPlaybackPresenter.onViewInitialized(); // init all controllers
|
||||
createPlayerObjects();
|
||||
mPlaybackPresenter.onEngineInitialized(); // start playback
|
||||
}
|
||||
|
||||
private void onVideoLoaded() {
|
||||
if (mOnLoad != null) {
|
||||
mOnLoad.run();
|
||||
mOnLoad = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void setOnLoad(Runnable onLoad) {
|
||||
mOnLoad = onLoad;
|
||||
}
|
||||
}
|
||||
|
@ -12,20 +12,10 @@
|
||||
android:scaleType="centerCrop"
|
||||
android:adjustViewBounds="true"
|
||||
tools:ignore="ContentDescription"/>
|
||||
<ImageView
|
||||
android:visibility="gone"
|
||||
android:id="@+id/preview_image"
|
||||
<FrameLayout
|
||||
android:id="@+id/preview_container"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:scaleType="centerCrop"
|
||||
android:adjustViewBounds="true"
|
||||
tools:ignore="ContentDescription"/>
|
||||
<com.liskovsoft.smartyoutubetv2.tv.ui.widgets.embedplayer.EmbedPlayerView
|
||||
android:visibility="gone"
|
||||
android:id="@+id/preview_player"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:use_controller="false"/>
|
||||
android:layout_height="wrap_content" />
|
||||
<LinearLayout
|
||||
android:id="@+id/clip_info"
|
||||
android:layout_width="match_parent"
|
||||
|
@ -4,14 +4,10 @@
|
||||
android:id="@+id/main_image"
|
||||
tools:ignore="ContentDescription"
|
||||
style="?attr/imageCardViewImageStyle"/>
|
||||
<ImageView
|
||||
android:visibility="gone"
|
||||
android:id="@+id/preview_image"
|
||||
<FrameLayout
|
||||
android:id="@+id/preview_container"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:scaleType="centerCrop"
|
||||
android:adjustViewBounds="true"
|
||||
tools:ignore="ContentDescription"/>
|
||||
android:layout_height="wrap_content" />
|
||||
<LinearLayout
|
||||
android:id="@+id/clip_info"
|
||||
android:layout_width="match_parent"
|
||||
|
Reference in New Issue
Block a user