Skip to content

Commit

Permalink
Fix crash when starting player where playback controller may be null
Browse files Browse the repository at this point in the history
  • Loading branch information
nielsvanvelzen committed Dec 17, 2023
1 parent 0c1aac9 commit 32849f5
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,6 @@ public class CustomPlaybackOverlayFragment extends Fragment implements LiveTvGui
private List<ChannelInfoDto> mAllChannels;
private String mFirstFocusChannelId;

private PlaybackController mPlaybackController;
private List<org.jellyfin.sdk.model.api.BaseItemDto> mItemsToPlay;

private Animation fadeOut;
Expand Down Expand Up @@ -195,7 +194,6 @@ public void onCreate(Bundle savedInstanceState) {
int mediaPosition = videoQueueManager.getValue().getCurrentMediaPosition();

playbackControllerContainer.getValue().setPlaybackController(new PlaybackController(mItemsToPlay, this, mediaPosition));
mPlaybackController = playbackControllerContainer.getValue().getPlaybackController();

// setup fade task
mHideTask = () -> {
Expand Down Expand Up @@ -350,15 +348,15 @@ public void onScrollChanged(ObservableHorizontalScrollView scrollView, int x, in
int startPos = getArguments().getInt("Position", 0);

// start playing
mPlaybackController.play(startPos);
playbackControllerContainer.getValue().getPlaybackController().play(startPos);
leanbackOverlayFragment.updatePlayState();

}

private void prepareOverlayFragment() {
leanbackOverlayFragment = (LeanbackOverlayFragment) getChildFragmentManager().findFragmentById(R.id.leanback_fragment);
if (leanbackOverlayFragment != null) {
leanbackOverlayFragment.initFromView(mPlaybackController, this);
leanbackOverlayFragment.initFromView(this);
leanbackOverlayFragment.mediaInfoChanged();
leanbackOverlayFragment.setOnKeyInterceptListener(keyListener);
}
Expand Down Expand Up @@ -403,7 +401,7 @@ public void onAnimationRepeat(Animation animation) {
public void onAudioFocusChange(int focusChange) {
switch (focusChange) {
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
mPlaybackController.pause();
playbackControllerContainer.getValue().getPlaybackController().pause();
break;
case AudioManager.AUDIOFOCUS_LOSS:
// We don't do anything here on purpose
Expand All @@ -424,7 +422,7 @@ public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item,
switch (rowItem.getBaseRowType()) {
case Chapter:
Long start = rowItem.getChapterInfo().getStartPositionTicks() / 10000;
mPlaybackController.seek(start);
playbackControllerContainer.getValue().getPlaybackController().seek(start);
hidePopupPanel();
break;
}
Expand All @@ -445,7 +443,7 @@ public void handleOnBackPressed() {
leanbackOverlayFragment.hideOverlay();

// also close this if live tv
if (mPlaybackController.isLiveTv()) hide();
if (playbackControllerContainer.getValue().getPlaybackController().isLiveTv()) hide();
} else if (mGuideVisible) {
hideGuide();
} else {
Expand Down Expand Up @@ -490,19 +488,19 @@ else if (mSelectedProgramView instanceof GuideChannelHeader)
}

if (keyCode == KeyEvent.KEYCODE_MEDIA_PLAY) {
mPlaybackController.play(0);
playbackControllerContainer.getValue().getPlaybackController().play(0);
return true;
} else if (keyCode == KeyEvent.KEYCODE_MEDIA_PAUSE) {
mPlaybackController.pause();
playbackControllerContainer.getValue().getPlaybackController().pause();
return true;
} else if (keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE) {
mPlaybackController.playPause();
playbackControllerContainer.getValue().getPlaybackController().playPause();
return true;
} else if (keyCode == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD || keyCode == KeyEvent.KEYCODE_BUTTON_R1 || keyCode == KeyEvent.KEYCODE_BUTTON_R2) {
mPlaybackController.fastForward();
playbackControllerContainer.getValue().getPlaybackController().fastForward();
return true;
} else if (keyCode == KeyEvent.KEYCODE_MEDIA_REWIND || keyCode == KeyEvent.KEYCODE_BUTTON_L1 || keyCode == KeyEvent.KEYCODE_BUTTON_L2) {
mPlaybackController.rewind();
playbackControllerContainer.getValue().getPlaybackController().rewind();
return true;
}
}
Expand Down Expand Up @@ -559,15 +557,15 @@ public boolean onKey(View v, int keyCode, KeyEvent event) {
leanbackOverlayFragment.hideOverlay();

// also close this if live tv
if (mPlaybackController.isLiveTv()) hide();
if (playbackControllerContainer.getValue().getPlaybackController().isLiveTv()) hide();
return true;
} else if (mGuideVisible) {
hideGuide();
return true;
}
}

if (mPlaybackController.isLiveTv() && !mPopupPanelVisible && !mGuideVisible && keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
if (playbackControllerContainer.getValue().getPlaybackController().isLiveTv() && !mPopupPanelVisible && !mGuideVisible && keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
if (!leanbackOverlayFragment.isControlsOverlayVisible()) {
leanbackOverlayFragment.setShouldShowOverlay(false);
leanbackOverlayFragment.hideOverlay();
Expand Down Expand Up @@ -596,7 +594,7 @@ public boolean onKey(View v, int keyCode, KeyEvent event) {
}
}

if (mPlaybackController.isLiveTv() && keyCode == KeyEvent.KEYCODE_MENU || keyCode == KeyEvent.KEYCODE_BUTTON_Y) {
if (playbackControllerContainer.getValue().getPlaybackController().isLiveTv() && keyCode == KeyEvent.KEYCODE_MENU || keyCode == KeyEvent.KEYCODE_BUTTON_Y) {
showGuide();
return true;
}
Expand All @@ -612,30 +610,30 @@ public boolean onKey(View v, int keyCode, KeyEvent event) {
// up or down should close panel
if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN || keyCode == KeyEvent.KEYCODE_DPAD_UP) {
hidePopupPanel();
if (mPlaybackController.isLiveTv()) hide(); //also close this if live tv
if (playbackControllerContainer.getValue().getPlaybackController().isLiveTv()) hide(); //also close this if live tv
return true;
} else {
return false;
}
}

// Control fast forward and rewind if overlay hidden and not showing live TV
if (!mPlaybackController.isLiveTv()) {
if (!playbackControllerContainer.getValue().getPlaybackController().isLiveTv()) {
if (keyCode == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD || keyCode == KeyEvent.KEYCODE_BUTTON_R1 || keyCode == KeyEvent.KEYCODE_BUTTON_R2) {
mPlaybackController.fastForward();
playbackControllerContainer.getValue().getPlaybackController().fastForward();
setFadingEnabled(true);
return true;
}

if (keyCode == KeyEvent.KEYCODE_MEDIA_REWIND || keyCode == KeyEvent.KEYCODE_BUTTON_L1 || keyCode == KeyEvent.KEYCODE_BUTTON_L2) {
mPlaybackController.rewind();
playbackControllerContainer.getValue().getPlaybackController().rewind();
setFadingEnabled(true);
return true;
}
}

if (!mIsVisible) {
if (!mPlaybackController.isLiveTv()) {
if (!playbackControllerContainer.getValue().getPlaybackController().isLiveTv()) {
if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
setFadingEnabled(true);
return true;
Expand All @@ -648,10 +646,10 @@ public boolean onKey(View v, int keyCode, KeyEvent event) {
}

if ((keyCode == KeyEvent.KEYCODE_DPAD_CENTER || keyCode == KeyEvent.KEYCODE_ENTER)
&& mPlaybackController.canSeek()) {
&& playbackControllerContainer.getValue().getPlaybackController().canSeek()) {
// if the player is playing and the overlay is hidden, this will pause
// if the player is paused and then 'back' is pressed to hide the overlay, this will play
mPlaybackController.playPause();
playbackControllerContainer.getValue().getPlaybackController().playPause();
return true;
}

Expand Down Expand Up @@ -688,12 +686,12 @@ public void switchChannel(String id) {

public void switchChannel(String id, boolean hideGuide) {
if (Utils.isEmpty(id)) return;
if (mPlaybackController.getCurrentlyPlayingItem().getId().equals(id)) {
if (playbackControllerContainer.getValue().getPlaybackController().getCurrentlyPlayingItem().getId().equals(id)) {
// same channel, just dismiss overlay
if (hideGuide)
hideGuide();
} else {
mPlaybackController.stop();
playbackControllerContainer.getValue().getPlaybackController().stop();
if (hideGuide)
hideGuide();
apiClient.getValue().GetItemAsync(id, KoinJavaComponent.<UserRepository>get(UserRepository.class).getCurrentUser().getValue().getId().toString(), new LifecycleAwareResponse<BaseItemDto>(getLifecycle()) {
Expand All @@ -703,8 +701,8 @@ public void onResponse(BaseItemDto response) {

List<org.jellyfin.sdk.model.api.BaseItemDto> items = new ArrayList<org.jellyfin.sdk.model.api.BaseItemDto>();
items.add(ModelCompat.asSdk(response));
mPlaybackController.setItems(items);
mPlaybackController.play(0);
playbackControllerContainer.getValue().getPlaybackController().setItems(items);
playbackControllerContainer.getValue().getPlaybackController().play(0);
}

@Override
Expand All @@ -729,7 +727,7 @@ public void onResume() {
super.onResume();

// Close player when resuming without a valid playback contoller
if (!mPlaybackController.hasFragment()) {
if (!playbackControllerContainer.getValue().getPlaybackController().hasFragment()) {
if (navigationRepository.getValue().getCanGoBack()) {
navigationRepository.getValue().goBack();
} else {
Expand Down Expand Up @@ -774,9 +772,9 @@ public void onStop() {

// end playback from here if this fragment belongs to the current session.
// if it doesn't, playback has already been stopped elsewhere, and the references to this have been replaced
if (mPlaybackController != null && mPlaybackController.getFragment() == this) {
if (playbackControllerContainer.getValue().getPlaybackController() != null && playbackControllerContainer.getValue().getPlaybackController().getFragment() == this) {
Timber.d("this fragment belongs to the current session, ending it");
mPlaybackController.endPlayback();
playbackControllerContainer.getValue().getPlaybackController().endPlayback();
}

// Reset display mode back to "no preference"
Expand Down Expand Up @@ -812,7 +810,7 @@ public void showGuide() {
hide();
leanbackOverlayFragment.setShouldShowOverlay(false);
leanbackOverlayFragment.hideOverlay();
mPlaybackController.mVideoManager.contractVideo(Utils.convertDpToPixel(requireContext(), 300));
playbackControllerContainer.getValue().getPlaybackController().mVideoManager.contractVideo(Utils.convertDpToPixel(requireContext(), 300));
tvGuideBinding.getRoot().setVisibility(View.VISIBLE);
mGuideVisible = true;
Calendar now = Calendar.getInstance();
Expand All @@ -831,7 +829,7 @@ public void showGuide() {

private void hideGuide() {
tvGuideBinding.getRoot().setVisibility(View.GONE);
mPlaybackController.mVideoManager.setVideoFullSize(true);
playbackControllerContainer.getValue().getPlaybackController().mVideoManager.setVideoFullSize(true);
mGuideVisible = false;
}

Expand Down Expand Up @@ -904,7 +902,7 @@ protected void onPreExecute() {
Timber.d("*** Display programs pre-execute");
tvGuideBinding.channels.removeAllViews();
tvGuideBinding.programRows.removeAllViews();
mFirstFocusChannelId = mPlaybackController.getCurrentlyPlayingItem().getId().toString();
mFirstFocusChannelId = playbackControllerContainer.getValue().getPlaybackController().getCurrentlyPlayingItem().getId().toString();

if (mCurrentDisplayChannelStartNdx > 0) {
// Show a paging row for channels above
Expand Down Expand Up @@ -1238,7 +1236,7 @@ public void showChapterSelector() {
mHandler.postDelayed(() -> {
if (!getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED)) return;

int ndx = getCurrentChapterIndex(mPlaybackController.getCurrentlyPlayingItem(), mPlaybackController.getCurrentPosition() * 10000);
int ndx = getCurrentChapterIndex(playbackControllerContainer.getValue().getPlaybackController().getCurrentlyPlayingItem(), playbackControllerContainer.getValue().getPlaybackController().getCurrentPosition() * 10000);
if (ndx > 0) {
mPopupRowPresenter.setPosition(ndx);
}
Expand Down Expand Up @@ -1303,7 +1301,7 @@ public void onResponse() {
if (!getActive()) return;

Utils.showToast(requireContext(), R.string.msg_recording_cancelled);
mPlaybackController.updateTvProgramInfo();
playbackControllerContainer.getValue().getPlaybackController().updateTvProgramInfo();
TvManager.forceReload();
}

Expand All @@ -1321,7 +1319,7 @@ public void onResponse() {
if (!getActive()) return;

Utils.showToast(requireContext(), R.string.msg_recording_cancelled);
mPlaybackController.updateTvProgramInfo();
playbackControllerContainer.getValue().getPlaybackController().updateTvProgramInfo();
TvManager.forceReload();
}

Expand Down Expand Up @@ -1351,7 +1349,7 @@ public void onResponse() {
if (!getActive()) return;

Utils.showToast(requireContext(), R.string.msg_set_to_record);
mPlaybackController.updateTvProgramInfo();
playbackControllerContainer.getValue().getPlaybackController().updateTvProgramInfo();
TvManager.forceReload();
}

Expand All @@ -1369,7 +1367,7 @@ public void onResponse() {
if (!getActive()) return;

Utils.showToast(requireContext(), R.string.msg_set_to_record);
mPlaybackController.updateTvProgramInfo();
playbackControllerContainer.getValue().getPlaybackController().updateTvProgramInfo();
TvManager.forceReload();
}

Expand Down Expand Up @@ -1409,7 +1407,7 @@ public void setPlayPauseActionState(final int state) {
}

public void updateDisplay() {
org.jellyfin.sdk.model.api.BaseItemDto current = mPlaybackController.getCurrentlyPlayingItem();
org.jellyfin.sdk.model.api.BaseItemDto current = playbackControllerContainer.getValue().getPlaybackController().getCurrentlyPlayingItem();
if (current != null && getContext() != null) {
leanbackOverlayFragment.mediaInfoChanged();
leanbackOverlayFragment.onFullyInitialized();
Expand Down Expand Up @@ -1437,7 +1435,7 @@ public void updateDisplay() {
binding.itemTitle.setVisibility(View.VISIBLE);
}

if (mPlaybackController.isLiveTv()) {
if (playbackControllerContainer.getValue().getPlaybackController().isLiveTv()) {
prepareChannelAdapter();
} else {
prepareChapterAdapter();
Expand All @@ -1446,7 +1444,7 @@ public void updateDisplay() {
}

private void prepareChapterAdapter() {
org.jellyfin.sdk.model.api.BaseItemDto item = mPlaybackController.getCurrentlyPlayingItem();
org.jellyfin.sdk.model.api.BaseItemDto item = playbackControllerContainer.getValue().getPlaybackController().getCurrentlyPlayingItem();
List<ChapterInfo> chapters = item.getChapters();

if (chapters != null && !chapters.isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,9 @@
import org.jellyfin.androidtv.ui.playback.PlaybackControllerContainer;

import kotlin.Lazy;
import timber.log.Timber;

public class LeanbackOverlayFragment extends PlaybackSupportFragment {

private PlaybackController playbackController;
private CustomPlaybackTransportControlGlue playerGlue;
private VideoPlayerAdapter playerAdapter;
private boolean shouldShowOverlay = true;
Expand All @@ -27,14 +26,17 @@ public void onCreate(Bundle savedInstanceState) {
setBackgroundType(BG_LIGHT);

PlaybackController playbackController = playbackControllerContainer.getValue().getPlaybackController();
if (playbackController == null) {
Timber.w("PlaybackController is null, skipping initialization.");
return;
}

playerAdapter = new VideoPlayerAdapter(playbackController, this);
playerGlue = new CustomPlaybackTransportControlGlue(getContext(), playerAdapter, playbackController);
playerGlue.setHost(new CustomPlaybackFragmentGlueHost(this));
}

public void initFromView(PlaybackController playbackController, CustomPlaybackOverlayFragment customPlaybackOverlayFragment) {
this.playbackController = playbackController;
public void initFromView(CustomPlaybackOverlayFragment customPlaybackOverlayFragment) {
playerGlue.setInitialPlaybackDrawable();
playerAdapter.setMasterOverlayFragment(customPlaybackOverlayFragment);
}
Expand Down Expand Up @@ -69,7 +71,7 @@ public void setFading(boolean fadingEnabled) {
}

public void mediaInfoChanged() {
org.jellyfin.sdk.model.api.BaseItemDto currentlyPlayingItem = playbackController.getCurrentlyPlayingItem();
org.jellyfin.sdk.model.api.BaseItemDto currentlyPlayingItem = playbackControllerContainer.getValue().getPlaybackController().getCurrentlyPlayingItem();
if (currentlyPlayingItem == null) return;

playerGlue.invalidatePlaybackControls();
Expand Down

0 comments on commit 32849f5

Please sign in to comment.