Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify video player preference #3663

Merged
merged 1 commit into from
Jun 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
package org.jellyfin.androidtv.preference

import android.content.Context
import org.jellyfin.androidtv.preference.constant.PreferredVideoPlayer
import org.jellyfin.preference.booleanPreference
import org.jellyfin.preference.enumPreference
import org.jellyfin.preference.store.SharedPreferenceStore
import org.jellyfin.preference.stringPreference

Expand Down Expand Up @@ -60,11 +58,6 @@ class SystemPreferences(context: Context) : SharedPreferenceStore(
val liveTvGuideFilterSports = booleanPreference("guide_filter_sports", false)

// Other persistent variables
/**
* Chosen player for play with button. Changes every time user chooses a player with "play with" button.
*/
var chosenPlayer = enumPreference("chosen_player", PreferredVideoPlayer.EXOPLAYER)

/**
* The version name for the latest dismissed beta notification or empty if none.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import org.jellyfin.androidtv.preference.constant.AppTheme
import org.jellyfin.androidtv.preference.constant.AudioBehavior
import org.jellyfin.androidtv.preference.constant.ClockBehavior
import org.jellyfin.androidtv.preference.constant.NextUpBehavior
import org.jellyfin.androidtv.preference.constant.PreferredVideoPlayer
import org.jellyfin.androidtv.preference.constant.RatingType
import org.jellyfin.androidtv.preference.constant.RefreshRateSwitchingBehavior
import org.jellyfin.androidtv.preference.constant.WatchedIndicatorBehavior
Expand Down Expand Up @@ -84,9 +83,9 @@ class UserPreferences(context: Context) : SharedPreferenceStore(

/* Playback - Video */
/**
* Preferred video player.
* Whether to use an external playback application or not.
*/
var videoPlayer = enumPreference("video_player", PreferredVideoPlayer.EXOPLAYER)
var useExternalPlayer = booleanPreference("external_player", false)

/**
* Change refresh rate to match media when device supports it
Expand Down Expand Up @@ -120,11 +119,6 @@ class UserPreferences(context: Context) : SharedPreferenceStore(
*/
var liveTvDirectPlayEnabled = booleanPreference("pref_live_direct", true)

/**
* Preferred video player for live TV
*/
var liveTvVideoPlayer = enumPreference("live_tv_video_player", PreferredVideoPlayer.EXOPLAYER)

/**
* Shortcut used for changing the audio track
*/
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,8 @@
import org.jellyfin.androidtv.data.repository.CustomMessageRepository;
import org.jellyfin.androidtv.data.service.BackgroundService;
import org.jellyfin.androidtv.databinding.FragmentFullDetailsBinding;
import org.jellyfin.androidtv.preference.SystemPreferences;
import org.jellyfin.androidtv.preference.UserPreferences;
import org.jellyfin.androidtv.preference.constant.ClockBehavior;
import org.jellyfin.androidtv.preference.constant.PreferredVideoPlayer;
import org.jellyfin.androidtv.ui.RecordPopup;
import org.jellyfin.androidtv.ui.RecordingIndicatorView;
import org.jellyfin.androidtv.ui.TextUnderButton;
Expand Down Expand Up @@ -151,7 +149,6 @@ public class FullDetailsFragment extends Fragment implements RecordingIndicatorV
private final Lazy<ApiClient> apiClient = inject(ApiClient.class);
private final Lazy<org.jellyfin.sdk.api.client.ApiClient> api = inject(org.jellyfin.sdk.api.client.ApiClient.class);
private final Lazy<UserPreferences> userPreferences = inject(UserPreferences.class);
final Lazy<SystemPreferences> systemPreferences = inject(SystemPreferences.class);
private final Lazy<DataRefreshService> dataRefreshService = inject(DataRefreshService.class);
private final Lazy<BackgroundService> backgroundService = inject(BackgroundService.class);
final Lazy<MediaManager> mediaManager = inject(MediaManager.class);
Expand Down Expand Up @@ -779,81 +776,59 @@ public void onClick(View v) {
}
});

//playButton becomes playWith button
if (userPreferences.getValue().get(UserPreferences.Companion.getVideoPlayer()) == PreferredVideoPlayer.CHOOSE && (baseItem.getType() == BaseItemKind.SERIES || baseItem.getType() == BaseItemKind.MOVIE || baseItem.getType() == BaseItemKind.VIDEO || baseItem.getType() == BaseItemKind.EPISODE)) {
playButton = TextUnderButton.create(requireContext(), R.drawable.ic_play, buttonSize, 3, getString(R.string.play_with), new View.OnClickListener() {
if (BaseItemExtensionsKt.canPlay(baseItem)) {
mDetailsOverviewRow.addAction(mResumeButton);
boolean resumeButtonVisible = (baseItem.getType() == BaseItemKind.SERIES && !mBaseItem.getUserData().getPlayed()) || (JavaCompat.getCanResume(mBaseItem));
mResumeButton.setVisibility(resumeButtonVisible ? View.VISIBLE : View.GONE);

playButton = TextUnderButton.create(requireContext(), R.drawable.ic_play, buttonSize, 2, getString(BaseItemExtensionsKt.isLiveTv(mBaseItem) ? R.string.lbl_tune_to_channel : mBaseItem.isFolder() ? R.string.lbl_play_all : R.string.lbl_play), new View.OnClickListener() {
@Override
public void onClick(View view) {
FullDetailsFragmentHelperKt.showPlayWithMenu(FullDetailsFragment.this, view, false);
public void onClick(View v) {
play(mBaseItem, 0, false);
}
});

mDetailsOverviewRow.addAction(playButton);

if (mBaseItem.isFolder()) {
if (resumeButtonVisible) {
mResumeButton.requestFocus();
} else {
playButton.requestFocus();
}

boolean isMusic = baseItem.getType() == BaseItemKind.MUSIC_ALBUM
|| baseItem.getType() == BaseItemKind.MUSIC_ARTIST
|| baseItem.getType() == BaseItemKind.AUDIO
|| (baseItem.getType() == BaseItemKind.PLAYLIST && MediaType.AUDIO.equals(baseItem.getMediaType()));

if (isMusic) {
queueButton = TextUnderButton.create(requireContext(), R.drawable.ic_add, buttonSize, 2, getString(R.string.lbl_add_to_queue), new View.OnClickListener() {
@Override
public void onClick(View v) {
addItemToQueue();
}
});
mDetailsOverviewRow.addAction(queueButton);
}

if (mBaseItem.isFolder() || baseItem.getType() == BaseItemKind.MUSIC_ARTIST) {
shuffleButton = TextUnderButton.create(requireContext(), R.drawable.ic_shuffle, buttonSize, 2, getString(R.string.lbl_shuffle_all), new View.OnClickListener() {
@Override
public void onClick(View view) {
FullDetailsFragmentHelperKt.showPlayWithMenu(FullDetailsFragment.this, view, true);
public void onClick(View v) {
play(mBaseItem, 0, true);
}
});
mDetailsOverviewRow.addAction(shuffleButton);
}
} else { //here playButton is only a play button
if (BaseItemExtensionsKt.canPlay(baseItem)) {
mDetailsOverviewRow.addAction(mResumeButton);
boolean resumeButtonVisible = (baseItem.getType() == BaseItemKind.SERIES && !mBaseItem.getUserData().getPlayed()) || (JavaCompat.getCanResume(mBaseItem));
mResumeButton.setVisibility(resumeButtonVisible ? View.VISIBLE : View.GONE);

playButton = TextUnderButton.create(requireContext(), R.drawable.ic_play, buttonSize, 2, getString(BaseItemExtensionsKt.isLiveTv(mBaseItem) ? R.string.lbl_tune_to_channel : mBaseItem.isFolder() ? R.string.lbl_play_all : R.string.lbl_play), new View.OnClickListener() {
if (baseItem.getType() == BaseItemKind.MUSIC_ARTIST) {
TextUnderButton imix = TextUnderButton.create(requireContext(), R.drawable.ic_mix, buttonSize, 0, getString(R.string.lbl_instant_mix), new View.OnClickListener() {
@Override
public void onClick(View v) {
play(mBaseItem, 0, false);
playbackHelper.getValue().playInstantMix(requireContext(), baseItem);
}
});

mDetailsOverviewRow.addAction(playButton);

if (resumeButtonVisible) {
mResumeButton.requestFocus();
} else {
playButton.requestFocus();
}

boolean isMusic = baseItem.getType() == BaseItemKind.MUSIC_ALBUM
|| baseItem.getType() == BaseItemKind.MUSIC_ARTIST
|| baseItem.getType() == BaseItemKind.AUDIO
|| (baseItem.getType() == BaseItemKind.PLAYLIST && MediaType.AUDIO.equals(baseItem.getMediaType()));

if (isMusic) {
queueButton = TextUnderButton.create(requireContext(), R.drawable.ic_add, buttonSize, 2, getString(R.string.lbl_add_to_queue), new View.OnClickListener() {
@Override
public void onClick(View v) {
addItemToQueue();
}
});
mDetailsOverviewRow.addAction(queueButton);
}

if (mBaseItem.isFolder() || baseItem.getType() == BaseItemKind.MUSIC_ARTIST) {
shuffleButton = TextUnderButton.create(requireContext(), R.drawable.ic_shuffle, buttonSize, 2, getString(R.string.lbl_shuffle_all), new View.OnClickListener() {
@Override
public void onClick(View v) {
play(mBaseItem, 0, true);
}
});
mDetailsOverviewRow.addAction(shuffleButton);
}

if (baseItem.getType() == BaseItemKind.MUSIC_ARTIST) {
TextUnderButton imix = TextUnderButton.create(requireContext(), R.drawable.ic_mix, buttonSize, 0, getString(R.string.lbl_instant_mix), new View.OnClickListener() {
@Override
public void onClick(View v) {
playbackHelper.getValue().playInstantMix(requireContext(), baseItem);
}
});
mDetailsOverviewRow.addAction(imix);
}

mDetailsOverviewRow.addAction(imix);
}
}
//Video versions button
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,8 @@ import kotlinx.coroutines.withContext
import org.jellyfin.androidtv.R
import org.jellyfin.androidtv.data.model.DataRefreshService
import org.jellyfin.androidtv.data.repository.ItemMutationRepository
import org.jellyfin.androidtv.preference.SystemPreferences
import org.jellyfin.androidtv.preference.constant.PreferredVideoPlayer
import org.jellyfin.androidtv.ui.navigation.Destinations
import org.jellyfin.androidtv.ui.navigation.NavigationRepository
import org.jellyfin.androidtv.util.apiclient.LifecycleAwareResponse
import org.jellyfin.androidtv.util.apiclient.getSeriesOverview
import org.jellyfin.androidtv.util.popupMenu
import org.jellyfin.androidtv.util.sdk.TrailerUtils.getExternalTrailerIntent
Expand Down Expand Up @@ -104,41 +101,6 @@ fun FullDetailsFragment.showDetailsMenu(
}
}.showIfNotEmpty()

fun FullDetailsFragment.showPlayWithMenu(
view: View,
shuffle: Boolean,
) = popupMenu(requireContext(), view) {
item(getString(R.string.play_with_exo_player)) {
systemPreferences.value[SystemPreferences.chosenPlayer] = PreferredVideoPlayer.EXOPLAYER
play(mBaseItem, 0, shuffle)
}

item(getString(R.string.play_with_external_app)) {
systemPreferences.value[SystemPreferences.chosenPlayer] = PreferredVideoPlayer.EXTERNAL

val itemsCallback = object : LifecycleAwareResponse<List<BaseItemDto>>(lifecycle) {
override fun onResponse(response: List<BaseItemDto>) {
if (!active) return

if (mBaseItem.type == BaseItemKind.MUSIC_ARTIST) {
mediaManager.value.playNow(requireContext(), response, 0, false)
} else {
videoQueueManager.value.setCurrentVideoQueue(response)
navigationRepository.value.navigate(Destinations.externalPlayer(0))
}
}
}

playbackHelper.value.getItemsToPlay(
requireContext(),
mBaseItem,
false,
shuffle,
itemsCallback
)
}
}.show()

fun FullDetailsFragment.createFakeSeriesTimerBaseItemDto(timer: SeriesTimerInfoDto) = BaseItemDto(
id = requireNotNull(timer.id).toUUID(),
type = BaseItemKind.FOLDER,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -217,8 +217,7 @@ public void onClick(DialogInterface dialog, int which) {
.setNegativeButton(R.string.turn_off, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
userPreferences.getValue().reset(UserPreferences.Companion.getVideoPlayer());
userPreferences.getValue().reset(UserPreferences.Companion.getLiveTvVideoPlayer());
userPreferences.getValue().reset(UserPreferences.Companion.getUseExternalPlayer());
}
})
.setOnDismissListener(new DialogInterface.OnDismissListener() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import org.jellyfin.androidtv.preference.UserPreferences;
import org.jellyfin.androidtv.preference.UserSettingPreferences;
import org.jellyfin.androidtv.preference.constant.NextUpBehavior;
import org.jellyfin.androidtv.preference.constant.PreferredVideoPlayer;
import org.jellyfin.androidtv.preference.constant.RefreshRateSwitchingBehavior;
import org.jellyfin.androidtv.ui.livetv.TvManager;
import org.jellyfin.androidtv.util.TimeUtils;
Expand Down Expand Up @@ -550,11 +549,6 @@ public void onError(Exception exception) {
@Override
public void onResponse(StreamInfo internalResponse) {
Timber.i("Internal player would %s", internalResponse.getPlayMethod().equals(PlayMethod.Transcode) ? "transcode" : "direct stream");

PreferredVideoPlayer preferredVideoPlayer = userPreferences.getValue().get(UserPreferences.Companion.getVideoPlayer());

Timber.i("User preferred player is: %s", preferredVideoPlayer);
Timber.i("Will use internal player");
if (mVideoManager == null)
return;
mCurrentOptions = internalOptions;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package org.jellyfin.androidtv.ui.playback

import org.jellyfin.androidtv.preference.UserPreferences
import org.jellyfin.androidtv.preference.constant.PreferredVideoPlayer
import org.jellyfin.androidtv.ui.navigation.Destination
import org.jellyfin.androidtv.ui.navigation.Destinations
import org.jellyfin.sdk.model.api.BaseItemKind
Expand All @@ -21,11 +20,9 @@ class GarbagePlaybackLauncher(
BaseItemKind.SERIES,
BaseItemKind.SEASON,
BaseItemKind.RECORDING,
-> userPreferences[UserPreferences.videoPlayer] === PreferredVideoPlayer.EXTERNAL

BaseItemKind.TV_CHANNEL,
BaseItemKind.PROGRAM,
-> userPreferences[UserPreferences.liveTvVideoPlayer] === PreferredVideoPlayer.EXTERNAL
-> userPreferences[UserPreferences.useExternalPlayer]

else -> false
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import android.os.Build
import org.jellyfin.androidtv.R
import org.jellyfin.androidtv.constant.getQualityProfiles
import org.jellyfin.androidtv.preference.UserPreferences
import org.jellyfin.androidtv.preference.constant.PreferredVideoPlayer
import org.jellyfin.androidtv.preference.constant.RefreshRateSwitchingBehavior
import org.jellyfin.androidtv.ui.preference.dsl.OptionsFragment
import org.jellyfin.androidtv.ui.preference.dsl.checkbox
Expand Down Expand Up @@ -49,11 +48,6 @@ class PlaybackAdvancedPreferencesScreen : OptionsFragment() {
category {
setTitle(R.string.pref_video)

enum<PreferredVideoPlayer> {
setTitle(R.string.pref_media_player)
bind(userPreferences, UserPreferences.videoPlayer)
}

@Suppress("MagicNumber")
list {
setTitle(R.string.pref_max_bitrate_title)
Expand All @@ -64,18 +58,17 @@ class PlaybackAdvancedPreferencesScreen : OptionsFragment() {
enum<RefreshRateSwitchingBehavior> {
setTitle(R.string.lbl_refresh_switching)
bind(userPreferences, UserPreferences.refreshRateSwitchingBehavior)
depends { userPreferences[UserPreferences.videoPlayer] != PreferredVideoPlayer.EXTERNAL }
}

checkbox{
setTitle(R.string.pref_external_player)
bind(userPreferences, UserPreferences.useExternalPlayer)
}
}

category {
setTitle(R.string.pref_live_tv_cat)

enum<PreferredVideoPlayer> {
setTitle(R.string.pref_media_player)
bind(userPreferences, UserPreferences.liveTvVideoPlayer)
}

checkbox {
setTitle(R.string.lbl_direct_stream_live)
bind(userPreferences, UserPreferences.liveTvDirectPlayEnabled)
Expand All @@ -97,14 +90,12 @@ class PlaybackAdvancedPreferencesScreen : OptionsFragment() {
setTitle(R.string.lbl_bitstream_ac3)
setContent(R.string.desc_bitstream_ac3)
bind(userPreferences, UserPreferences.ac3Enabled)
depends { userPreferences[UserPreferences.videoPlayer] != PreferredVideoPlayer.EXTERNAL }
}

checkbox {
setTitle(R.string.lbl_bitstream_dts)
setContent(R.string.desc_bitstream_ac3)
bind(userPreferences, UserPreferences.dtsEnabled)
depends { userPreferences[UserPreferences.videoPlayer] != PreferredVideoPlayer.EXTERNAL }
}
}
}
Expand Down
Loading
Loading