diff --git a/app/phone/src/main/java/dev/jdtech/jellyfin/PlayerActivity.kt b/app/phone/src/main/java/dev/jdtech/jellyfin/PlayerActivity.kt index 2048fd38..84982dbb 100644 --- a/app/phone/src/main/java/dev/jdtech/jellyfin/PlayerActivity.kt +++ b/app/phone/src/main/java/dev/jdtech/jellyfin/PlayerActivity.kt @@ -27,18 +27,15 @@ import androidx.lifecycle.Lifecycle import androidx.lifecycle.lifecycleScope import androidx.lifecycle.repeatOnLifecycle import androidx.media3.common.C -import androidx.media3.exoplayer.ExoPlayer import androidx.media3.ui.AspectRatioFrameLayout import androidx.media3.ui.DefaultTimeBar import androidx.media3.ui.PlayerView -import androidx.media3.ui.TrackSelectionDialogBuilder import androidx.navigation.navArgs import dagger.hilt.android.AndroidEntryPoint import dev.jdtech.jellyfin.databinding.ActivityPlayerBinding import dev.jdtech.jellyfin.dialogs.SpeedSelectionDialogFragment import dev.jdtech.jellyfin.dialogs.TrackSelectionDialogFragment import dev.jdtech.jellyfin.mpv.MPVPlayer -import dev.jdtech.jellyfin.mpv.TrackType import dev.jdtech.jellyfin.utils.PlayerGestureHelper import dev.jdtech.jellyfin.utils.PreviewScrubListener import dev.jdtech.jellyfin.viewmodels.PlayerActivityViewModel @@ -46,7 +43,6 @@ import dev.jdtech.jellyfin.viewmodels.PlayerEvents import kotlinx.coroutines.launch import timber.log.Timber import javax.inject.Inject -import dev.jdtech.jellyfin.player.video.R as PlayerVideoR var isControlsLocked: Boolean = false @@ -201,38 +197,10 @@ class PlayerActivity : BasePlayerActivity() { } audioButton.setOnClickListener { - when (viewModel.player) { - is MPVPlayer -> { - TrackSelectionDialogFragment(TrackType.AUDIO, viewModel).show( - supportFragmentManager, - "trackselectiondialog", - ) - } - is ExoPlayer -> { - val mappedTrackInfo = - viewModel.trackSelector.currentMappedTrackInfo ?: return@setOnClickListener - - var audioRenderer: Int? = null - for (i in 0 until mappedTrackInfo.rendererCount) { - if (isRendererType(mappedTrackInfo, i, C.TRACK_TYPE_AUDIO)) { - audioRenderer = i - } - } - - if (audioRenderer == null) return@setOnClickListener - - val trackSelectionDialogBuilder = TrackSelectionDialogBuilder( - this, - resources.getString(PlayerVideoR.string.select_audio_track), - viewModel.player, - C.TRACK_TYPE_AUDIO, - ) - trackSelectionDialogBuilder.setShowDisableOption(true) - - val trackSelectionDialog = trackSelectionDialogBuilder.build() - trackSelectionDialog.show() - } - } + TrackSelectionDialogFragment(C.TRACK_TYPE_AUDIO, viewModel).show( + supportFragmentManager, + "trackselectiondialog", + ) } val exoPlayerControlView = findViewById(R.id.player_controls) @@ -253,38 +221,10 @@ class PlayerActivity : BasePlayerActivity() { } subtitleButton.setOnClickListener { - when (viewModel.player) { - is MPVPlayer -> { - TrackSelectionDialogFragment(TrackType.SUBTITLE, viewModel).show( - supportFragmentManager, - "trackselectiondialog", - ) - } - is ExoPlayer -> { - val mappedTrackInfo = - viewModel.trackSelector.currentMappedTrackInfo ?: return@setOnClickListener - - var subtitleRenderer: Int? = null - for (i in 0 until mappedTrackInfo.rendererCount) { - if (isRendererType(mappedTrackInfo, i, C.TRACK_TYPE_TEXT)) { - subtitleRenderer = i - } - } - - if (subtitleRenderer == null) return@setOnClickListener - - val trackSelectionDialogBuilder = TrackSelectionDialogBuilder( - this, - resources.getString(PlayerVideoR.string.select_subtile_track), - viewModel.player, - C.TRACK_TYPE_TEXT, - ) - trackSelectionDialogBuilder.setShowDisableOption(true) - - val trackSelectionDialog = trackSelectionDialogBuilder.build() - trackSelectionDialog.show() - } - } + TrackSelectionDialogFragment(C.TRACK_TYPE_TEXT, viewModel).show( + supportFragmentManager, + "trackselectiondialog", + ) } speedButton.setOnClickListener { diff --git a/app/tv/src/main/java/dev/jdtech/jellyfin/ui/PlayerScreen.kt b/app/tv/src/main/java/dev/jdtech/jellyfin/ui/PlayerScreen.kt index 40909d11..e286e358 100644 --- a/app/tv/src/main/java/dev/jdtech/jellyfin/ui/PlayerScreen.kt +++ b/app/tv/src/main/java/dev/jdtech/jellyfin/ui/PlayerScreen.kt @@ -124,7 +124,7 @@ fun PlayerScreen( val trackType = result.value.trackType val index = result.value.index - if (result.value.index == -1) { + if (index == -1) { viewModel.player.trackSelectionParameters = viewModel.player.trackSelectionParameters .buildUpon() .clearOverridesOfType(trackType) diff --git a/player/video/src/main/java/dev/jdtech/jellyfin/dialogs/TrackSelectionDialogFragment.kt b/player/video/src/main/java/dev/jdtech/jellyfin/dialogs/TrackSelectionDialogFragment.kt index e249ea24..db9c5285 100644 --- a/player/video/src/main/java/dev/jdtech/jellyfin/dialogs/TrackSelectionDialogFragment.kt +++ b/player/video/src/main/java/dev/jdtech/jellyfin/dialogs/TrackSelectionDialogFragment.kt @@ -6,56 +6,36 @@ import androidx.fragment.app.DialogFragment import androidx.media3.common.C import com.google.android.material.dialog.MaterialAlertDialogBuilder import dev.jdtech.jellyfin.getTrackNames -import dev.jdtech.jellyfin.mpv.TrackType import dev.jdtech.jellyfin.player.video.R import dev.jdtech.jellyfin.viewmodels.PlayerActivityViewModel import java.lang.IllegalStateException class TrackSelectionDialogFragment( - private val type: TrackType, + private val type: @C.TrackType Int, private val viewModel: PlayerActivityViewModel, ) : DialogFragment() { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - when (type) { - TrackType.AUDIO -> { - return activity?.let { activity -> - val builder = MaterialAlertDialogBuilder(activity) - val tracksGroups = viewModel.player.currentTracks.groups.filter { it.type == C.TRACK_TYPE_AUDIO } - builder.setTitle(getString(R.string.select_audio_track)) - .setSingleChoiceItems( - arrayOf(getString(R.string.none)) + tracksGroups.getTrackNames(), // Add "None" at the top of the list - tracksGroups.indexOfFirst { it.isSelected } + 1, // Add 1 to the index to account for the "None" item - ) { dialog, which -> - viewModel.switchToTrack( - TrackType.AUDIO, - which - 1, // Minus 1 to get the correct group without the "None" item. "None" becomes -1 - ) - dialog.dismiss() - } - builder.create() - } ?: throw IllegalStateException("Activity cannot be null") - } - TrackType.SUBTITLE -> { - return activity?.let { activity -> - val builder = MaterialAlertDialogBuilder(activity) - val tracksGroups = viewModel.player.currentTracks.groups.filter { it.type == C.TRACK_TYPE_TEXT } - builder.setTitle(getString(R.string.select_subtile_track)) - .setSingleChoiceItems( - arrayOf(getString(R.string.none)) + tracksGroups.getTrackNames(), - tracksGroups.indexOfFirst { it.isSelected } + 1, - ) { dialog, which -> - viewModel.switchToTrack( - TrackType.SUBTITLE, - which - 1, - ) - dialog.dismiss() - } - builder.create() - } ?: throw IllegalStateException("Activity cannot be null") - } - else -> { - throw IllegalStateException("TrackType must be AUDIO or SUBTITLE") - } + val titleResource = when (type) { + C.TRACK_TYPE_AUDIO -> R.string.select_audio_track + C.TRACK_TYPE_TEXT -> R.string.select_subtile_track + else -> throw IllegalStateException("TrackType must be AUDIO or TEXT") } + val tracksGroups = viewModel.player.currentTracks.groups.filter { it.type == type && it.isSupported } + return activity?.let { activity -> + val builder = MaterialAlertDialogBuilder(activity) + builder + .setTitle(getString(titleResource)) + .setSingleChoiceItems( + arrayOf(getString(R.string.none)) + tracksGroups.getTrackNames(), // Add "None" at the top of the list + tracksGroups.indexOfFirst { it.isSelected } + 1, // Add 1 to the index to account for the "None" item + ) { dialog, which -> + viewModel.switchToTrack( + type, + which - 1, // Minus 1 to get the correct group without the "None" item. "None" becomes -1 + ) + dialog.dismiss() + } + builder.create() + } ?: throw IllegalStateException("Activity cannot be null") } } diff --git a/player/video/src/main/java/dev/jdtech/jellyfin/mpv/MPVPlayer.kt b/player/video/src/main/java/dev/jdtech/jellyfin/mpv/MPVPlayer.kt index 4f3d6377..6efbc2ee 100644 --- a/player/video/src/main/java/dev/jdtech/jellyfin/mpv/MPVPlayer.kt +++ b/player/video/src/main/java/dev/jdtech/jellyfin/mpv/MPVPlayer.kt @@ -354,7 +354,7 @@ class MPVPlayer( * @param id Id to select or [C.INDEX_UNSET] to disable [TrackType] * @return true if the track is or was already selected */ - fun selectTrack( + private fun selectTrack( trackType: TrackType, id: String, ) { diff --git a/player/video/src/main/java/dev/jdtech/jellyfin/viewmodels/PlayerActivityViewModel.kt b/player/video/src/main/java/dev/jdtech/jellyfin/viewmodels/PlayerActivityViewModel.kt index 53a358d0..b2ee5e9d 100644 --- a/player/video/src/main/java/dev/jdtech/jellyfin/viewmodels/PlayerActivityViewModel.kt +++ b/player/video/src/main/java/dev/jdtech/jellyfin/viewmodels/PlayerActivityViewModel.kt @@ -11,6 +11,7 @@ import androidx.media3.common.C import androidx.media3.common.MediaItem import androidx.media3.common.MediaMetadata import androidx.media3.common.Player +import androidx.media3.common.TrackSelectionOverride import androidx.media3.common.TrackSelectionParameters import androidx.media3.exoplayer.DefaultRenderersFactory import androidx.media3.exoplayer.ExoPlayer @@ -20,7 +21,6 @@ import dev.jdtech.jellyfin.AppPreferences import dev.jdtech.jellyfin.models.Intro import dev.jdtech.jellyfin.models.PlayerItem import dev.jdtech.jellyfin.mpv.MPVPlayer -import dev.jdtech.jellyfin.mpv.TrackType import dev.jdtech.jellyfin.player.video.R import dev.jdtech.jellyfin.repository.JellyfinRepository import dev.jdtech.jellyfin.utils.bif.BifData @@ -319,21 +319,22 @@ constructor( releasePlayer() } - fun switchToTrack(trackType: TrackType, index: Int) { - if (player is MPVPlayer) { - // Index -1 equals disable track - if (index == -1) { - player.selectTrack(trackType, id = "no") - return - } - - // Get track to select based on index - val tracksGroup = player.currentTracks.groups.filter { TrackType.fromMedia3TrackType(it.type) == trackType }[index] - val format = tracksGroup.mediaTrackGroup.getFormat(0) - if (format.id == null) { - return - } - player.selectTrack(trackType, id = format.id!!) + fun switchToTrack(trackType: @C.TrackType Int, index: Int) { + // Index -1 equals disable track + if (index == -1) { + player.trackSelectionParameters = player.trackSelectionParameters + .buildUpon() + .clearOverridesOfType(trackType) + .setTrackTypeDisabled(trackType, true) + .build() + } else { + player.trackSelectionParameters = player.trackSelectionParameters + .buildUpon() + .setOverrideForType( + TrackSelectionOverride(player.currentTracks.groups.filter { it.type == trackType && it.isSupported }[index].mediaTrackGroup, 0), + ) + .setTrackTypeDisabled(trackType, false) + .build() } }