diff --git a/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/controllers/SuggestionsController.java b/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/controllers/SuggestionsController.java index 352dd7355..98ed6fcbe 100644 --- a/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/controllers/SuggestionsController.java +++ b/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/controllers/SuggestionsController.java @@ -19,6 +19,7 @@ import com.liskovsoft.smartyoutubetv2.common.app.models.data.Playlist; import com.liskovsoft.smartyoutubetv2.common.app.models.data.Video; import com.liskovsoft.smartyoutubetv2.common.app.models.data.VideoGroup; import com.liskovsoft.smartyoutubetv2.common.app.models.playback.BasePlayerController; +import com.liskovsoft.smartyoutubetv2.common.app.models.playback.manager.PlayerConstants; import com.liskovsoft.smartyoutubetv2.common.app.models.playback.ui.OptionItem; import com.liskovsoft.smartyoutubetv2.common.app.models.playback.ui.SeekBarSegment; import com.liskovsoft.smartyoutubetv2.common.app.models.playback.ui.UiOptionItem; @@ -27,6 +28,7 @@ import com.liskovsoft.smartyoutubetv2.common.app.presenters.PlaybackPresenter; import com.liskovsoft.smartyoutubetv2.common.misc.DeArrowProcessor; import com.liskovsoft.smartyoutubetv2.common.misc.MediaServiceManager; import com.liskovsoft.smartyoutubetv2.common.prefs.GeneralData; +import com.liskovsoft.smartyoutubetv2.common.utils.UniqueRandom; import com.liskovsoft.smartyoutubetv2.common.utils.Utils; import com.liskovsoft.youtubeapi.service.YouTubeServiceManager; import io.reactivex.Observable; @@ -41,7 +43,7 @@ public class SuggestionsController extends BasePlayerController { private MediaItemService mMediaItemService; private ContentService mContentService; private DeArrowProcessor mDeArrowProcessor; - private Video mNextVideo; + private Video mNextSectionVideo; private int mFocusCount; private int mNextRetryCount; private List mChapters; @@ -279,8 +281,8 @@ public class SuggestionsController extends BasePlayerController { if (next != null) { next.fromQueue = true; result = next; - } else if (mNextVideo != null) { - result = mNextVideo; + } else if (mNextSectionVideo != null) { + result = mNextSectionVideo; } else if (current != null && current.nextMediaItem != null) { result = Video.from(current.nextMediaItem); } @@ -531,12 +533,12 @@ public class SuggestionsController extends BasePlayerController { private void appendSectionPlaylistIfNeeded(Video video) { if (!video.isSectionPlaylistEnabled(getContext())) { // Important fix. Gives priority to playlist or suggestion. - mNextVideo = null; + mNextSectionVideo = null; return; } getPlayer().updateSuggestions(video.getGroup()); - focusAndContinueIfNeeded(video.getGroup(), () -> appendNextSectionVideoIfNeeded(video)); + focusAndContinueIfNeeded(video.getGroup(), () -> findNextSectionVideoIfNeeded(video)); } private void markAsQueueIfNeeded(Video item) { @@ -644,12 +646,37 @@ public class SuggestionsController extends BasePlayerController { } } - private void appendNextSectionVideoIfNeeded(Video video) { + private void findNextSectionVideoIfNeeded(Video video) { if (!video.isSectionPlaylistEnabled(getContext())) { return; } - mNextVideo = null; + if (getPlayerData().getPlaybackMode() == PlayerConstants.PLAYBACK_MODE_SHUFFLE) { + findRandomSectionVideo(video); + } else { + findNextSectionVideo(video); + } + } + + private void findRandomSectionVideo(Video video) { + mNextSectionVideo = null; + + VideoGroup group = video.getGroup(); + + if (group == null || group.isEmpty()) { + return; + } + + int currentIdx = group.indexOf(video); + + int nextIdx = UniqueRandom.getRandomIndex(currentIdx, group.getSize()); + + mNextSectionVideo = group.get(nextIdx); + getPlayer().setNextTitle(mNextSectionVideo); + } + + private void findNextSectionVideo(Video video) { + mNextSectionVideo = null; VideoGroup group = video.getGroup(); @@ -663,8 +690,8 @@ public class SuggestionsController extends BasePlayerController { for (Video current : videos) { if (found && current.hasVideo() && !current.isUpcoming) { mNextRetryCount = 0; - mNextVideo = current; - getPlayer().setNextTitle(mNextVideo); + mNextSectionVideo = current; + getPlayer().setNextTitle(mNextSectionVideo); return; } @@ -676,7 +703,7 @@ public class SuggestionsController extends BasePlayerController { if (mNextRetryCount > 0) { mNextRetryCount = 0; } else { - continueGroup(group, continuation -> appendNextSectionVideoIfNeeded(video), getPlayer().isSuggestionsShown()); + continueGroup(group, continuation -> findNextSectionVideoIfNeeded(video), getPlayer().isSuggestionsShown()); mNextRetryCount++; } } @@ -770,7 +797,7 @@ public class SuggestionsController extends BasePlayerController { private void disposeActions() { RxHelper.disposeActions(mActions); mChapters = null; - mNextVideo = null; + mNextSectionVideo = null; } private void appendDislikes(Video video) { diff --git a/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/controllers/VideoLoaderController.java b/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/controllers/VideoLoaderController.java index 59fcdd987..36b015a36 100644 --- a/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/controllers/VideoLoaderController.java +++ b/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/controllers/VideoLoaderController.java @@ -44,7 +44,6 @@ public class VideoLoaderController extends BasePlayerController implements OnDat private static final long BUFFERING_WINDOW_MS = 60_000; private static final long BUFFERING_RECURRENCE_COUNT = (long) (BUFFERING_WINDOW_MS * 0.5 / BUFFERING_THRESHOLD_MS); private final Playlist mPlaylist; - private final UniqueRandom mRandom; private Video mPendingVideo; private int mLastErrorType = -1; private SuggestionsController mSuggestionsController; @@ -84,7 +83,6 @@ public class VideoLoaderController extends BasePlayerController implements OnDat public VideoLoaderController() { mPlaylist = Playlist.instance(); - mRandom = new UniqueRandom(); } @Override @@ -832,7 +830,10 @@ public class VideoLoaderController extends BasePlayerController implements OnDat Video video = new Video(); video.playlistId = getVideo().playlistId; VideoGroup topRow = getPlayer().getSuggestionsByIndex(0); - video.playlistIndex = mRandom.getPlaylistIndex(getVideo().getPlaylistId(), + //video.playlistIndex = mRandom.getPlaylistIndex(getVideo().getPlaylistId(), + // getVideo().playlistInfo.getSize() != -1 ? getVideo().playlistInfo.getSize() : topRow != null ? topRow.getVideos().size() : -1); + + video.playlistIndex = UniqueRandom.getRandomIndex(getVideo().getPositionInsideGroup(), getVideo().playlistInfo.getSize() != -1 ? getVideo().playlistInfo.getSize() : topRow != null ? topRow.getVideos().size() : -1); MediaServiceManager.instance().loadMetadata(video, randomMetadata -> { diff --git a/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/controllers/VideoStateController.java b/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/controllers/VideoStateController.java index 481169e42..375c3ed2d 100644 --- a/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/controllers/VideoStateController.java +++ b/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/controllers/VideoStateController.java @@ -408,7 +408,7 @@ public class VideoStateController extends BasePlayerController { savePosition(); - if (!isBeginEmbed()) { + if (!isBegin()) { updateHistory(); syncWithPlaylists(); } @@ -430,7 +430,7 @@ public class VideoStateController extends BasePlayerController { private void persistState() { // Skip mini player, but don't save for the previews (mute enabled) - if (isMutedEmbed() || isBeginEmbed()) { + if (isMutedEmbed() || isBegin()) { return; } @@ -682,4 +682,8 @@ public class VideoStateController extends BasePlayerController { private boolean isBeginEmbed() { return isEmbedPlayer() && System.currentTimeMillis() - mNewVideoTimeMs <= EMBED_THRESHOLD_MS; } + + private boolean isBegin() { + return System.currentTimeMillis() - mNewVideoTimeMs <= EMBED_THRESHOLD_MS; + } } diff --git a/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/utils/UniqueRandom.java b/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/utils/UniqueRandom.java index 72a2fb912..91d9c0ca5 100644 --- a/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/utils/UniqueRandom.java +++ b/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/utils/UniqueRandom.java @@ -2,36 +2,50 @@ package com.liskovsoft.smartyoutubetv2.common.utils; import com.liskovsoft.sharedutils.helpers.Helpers; -import java.util.ArrayList; -import java.util.List; - public class UniqueRandom { private static final int RANDOM_FAIL_REPEAT_TIMES = 10; - private List mUsedIndexes; - private int mPlaylistSize; - private String mPlaylistId; + //private List mUsedIndexes; + //private int mPlaylistSize; + //private String mPlaylistId; - public int getPlaylistIndex(int playlistSize) { - return getPlaylistIndex(null, playlistSize); - } + //public int getPlaylistIndex(int playlistSize) { + // return getPlaylistIndex(null, playlistSize); + //} + // + //public int getPlaylistIndex(String playlistId, int playlistSize) { + // if (mUsedIndexes == null) { + // mUsedIndexes = new ArrayList<>(); + // } + // + // if (!Helpers.equals(mPlaylistId, playlistId) || mPlaylistSize != playlistSize || mUsedIndexes.size() == playlistSize) { + // mUsedIndexes.clear(); + // mPlaylistSize = playlistSize; + // mPlaylistId = playlistId; + // } + // + // int randomIndex = 0; + // + // for (int i = 0; i < RANDOM_FAIL_REPEAT_TIMES; i++) { + // randomIndex = Helpers.getRandomIndex(playlistSize); + // if (!mUsedIndexes.contains(randomIndex)) { + // mUsedIndexes.add(randomIndex); + // break; + // } + // } + // + // return randomIndex; + //} - public int getPlaylistIndex(String playlistId, int playlistSize) { - if (mUsedIndexes == null) { - mUsedIndexes = new ArrayList<>(); - } - - if (!Helpers.equals(mPlaylistId, playlistId) || mPlaylistSize != playlistSize || mUsedIndexes.size() == playlistSize) { - mUsedIndexes.clear(); - mPlaylistSize = playlistSize; - mPlaylistId = playlistId; + public static int getRandomIndex(int currentIdx, int playlistSize) { + if (playlistSize <= 1) { + return 0; } int randomIndex = 0; for (int i = 0; i < RANDOM_FAIL_REPEAT_TIMES; i++) { randomIndex = Helpers.getRandomIndex(playlistSize); - if (!mUsedIndexes.contains(randomIndex)) { - mUsedIndexes.add(randomIndex); + if (randomIndex != currentIdx) { break; } } diff --git a/leanback-1.0.0/src/main/java/androidx/leanback/widget/GridLayoutManager.java b/leanback-1.0.0/src/main/java/androidx/leanback/widget/GridLayoutManager.java index 2fe189c0c..abae15977 100644 --- a/leanback-1.0.0/src/main/java/androidx/leanback/widget/GridLayoutManager.java +++ b/leanback-1.0.0/src/main/java/androidx/leanback/widget/GridLayoutManager.java @@ -2320,7 +2320,8 @@ final class GridLayoutManager extends RecyclerView.LayoutManager { try { appendVisibleItems(); prependVisibleItems(); - } catch (NullPointerException e) { + } catch (IndexOutOfBoundsException | NullPointerException e) { + // IndexOutOfBoundsException: Invalid item position -1(-1). Item count:12 androidx.leanback.widget.VerticalGridView // NullPointerException: Attempt to invoke virtual method 'android.view.ViewGroup$LayoutParams android.view.View.getLayoutParams()' e.printStackTrace(); }