diff --git a/core-model/src/main/java/hu/bbara/purefin/model/PlayableMedia.kt b/core-model/src/main/java/hu/bbara/purefin/model/PlayableMedia.kt index 4f009e6b..a6c9819a 100644 --- a/core-model/src/main/java/hu/bbara/purefin/model/PlayableMedia.kt +++ b/core-model/src/main/java/hu/bbara/purefin/model/PlayableMedia.kt @@ -5,6 +5,7 @@ import java.util.UUID sealed class PlayableMedia { abstract val id: UUID + abstract val preferenceMediaId: UUID abstract val resumePositionMs: Long abstract val mediaItem: MediaItem abstract val preferences: MediaTrackPreferences @@ -12,6 +13,7 @@ sealed class PlayableMedia { data class Movie( override val id: UUID, + override val preferenceMediaId: UUID, override val resumePositionMs: Long, override val mediaItem: MediaItem, override val preferences: MediaTrackPreferences, @@ -20,6 +22,7 @@ sealed class PlayableMedia { data class Series( override val id: UUID, + override val preferenceMediaId: UUID, override val resumePositionMs: Long, override val mediaItem: MediaItem, override val preferences: MediaTrackPreferences, @@ -28,6 +31,7 @@ sealed class PlayableMedia { data class Episode( override val id: UUID, + override val preferenceMediaId: UUID, override val resumePositionMs: Long, override val mediaItem: MediaItem, override val preferences: MediaTrackPreferences, diff --git a/core/src/main/java/hu/bbara/purefin/core/player/manager/PlayerManager.kt b/core/src/main/java/hu/bbara/purefin/core/player/manager/PlayerManager.kt index d98cd71f..4003e734 100644 --- a/core/src/main/java/hu/bbara/purefin/core/player/manager/PlayerManager.kt +++ b/core/src/main/java/hu/bbara/purefin/core/player/manager/PlayerManager.kt @@ -11,7 +11,6 @@ import androidx.media3.exoplayer.ExoPlayer import dagger.hilt.android.scopes.ViewModelScoped import hu.bbara.purefin.core.data.PlayableMediaRepository import hu.bbara.purefin.core.data.PlaybackReportContext -import hu.bbara.purefin.core.feature.content.episode.SeriesIdLookUpUseCase import hu.bbara.purefin.core.player.model.MetadataState import hu.bbara.purefin.core.player.model.PlaybackProgressSnapshot import hu.bbara.purefin.core.player.model.PlaybackStateSnapshot @@ -56,7 +55,6 @@ class PlayerManager @Inject constructor( private val playableMediaRepository: PlayableMediaRepository, private val trackPreferencesRepository: TrackPreferencesRepository, private val trackMatcher: TrackMatcher, - private val seriesIdLookUpUseCase: SeriesIdLookUpUseCase, private val settingsRepository: SettingsRepository ) { companion object { @@ -116,7 +114,8 @@ class PlayerManager @Inject constructor( override fun onMediaItemTransition(mediaItem: MediaItem?, reason: Int) { clearActiveSkippableSegment() - _currentMediaId.value = mediaItem?.mediaId?.let { UUID.fromString(it) } + val mediaId = mediaItem?.mediaId?.let { UUID.fromString(it) } + _currentMediaId.value = mediaId scope.launch { val currentMedia = _playlist.value.firstOrNull { it.id == _currentMediaId.value } if (currentMedia == null) { @@ -263,6 +262,15 @@ class PlayerManager @Inject constructor( } fun selectTrack(option: TrackOption) { + scope.launch { + if (option.type != TrackType.VIDEO) { + saveTrackPreference(option) + } + applyTrackSelection(option) + } + } + + private fun applyTrackSelection(option: TrackOption) { val builder = player.trackSelectionParameters.buildUpon() when (option.type) { TrackType.TEXT -> { @@ -296,13 +304,6 @@ class PlayerManager @Inject constructor( } } player.trackSelectionParameters = builder.build() - - // Save track preference if media id is available - _currentMediaId.value?.let { mediaId -> - scope.launch { - saveTrackPreference(option, mediaId) - } - } } private fun installMediaSegments(mediaSegments: List) { @@ -329,9 +330,14 @@ class PlayerManager @Inject constructor( } private suspend fun applyTrackPreferences() { - val preferences = currentPlayableMedia.firstOrNull()?.preferences ?: return - + val currentMedia = currentPlayableMedia.firstOrNull() ?: return val currentTrackState = _tracks.value + if (currentTrackState.audioTracks.isEmpty() && currentTrackState.textTracks.isEmpty()) return + + val preferences = trackPreferencesRepository + .getMediaPreferences(currentMedia.preferenceMediaId.toString()) + .firstOrNull() + ?: return // Apply audio preference preferences.audioPreference?.let { audioPreference -> @@ -339,7 +345,9 @@ class PlayerManager @Inject constructor( currentTrackState.audioTracks, audioPreference ) - matchedAudio?.let { selectTrack(it) } + if (matchedAudio != null && matchedAudio.id != currentTrackState.selectedAudioTrackId) { + applyTrackSelection(matchedAudio) + } } // Apply subtitle preference @@ -348,15 +356,17 @@ class PlayerManager @Inject constructor( currentTrackState.textTracks, subtitlePreference ) - matchedSubtitle?.let { selectTrack(it) } + if (matchedSubtitle != null && matchedSubtitle.id != currentTrackState.selectedTextTrackId) { + applyTrackSelection(matchedSubtitle) + } } } - private suspend fun saveTrackPreference(option: TrackOption, mediaId: UUID) { - val preferenceMediaId = when (currentPlayableMedia.firstOrNull()) { - is PlayableMedia.Episode -> seriesIdLookUpUseCase(mediaId) ?: mediaId - else -> mediaId - }.toString() + private suspend fun saveTrackPreference(option: TrackOption) { + val preferenceMediaId = currentPlayableMedia.firstOrNull() + ?.preferenceMediaId + ?.toString() + ?: return when (option.type) { TrackType.AUDIO -> { diff --git a/data/src/main/java/hu/bbara/purefin/data/jellyfin/DefaultPlayableMediaRepository.kt b/data/src/main/java/hu/bbara/purefin/data/jellyfin/DefaultPlayableMediaRepository.kt index cd11a7e0..29a5e825 100644 --- a/data/src/main/java/hu/bbara/purefin/data/jellyfin/DefaultPlayableMediaRepository.kt +++ b/data/src/main/java/hu/bbara/purefin/data/jellyfin/DefaultPlayableMediaRepository.kt @@ -48,11 +48,16 @@ class DefaultPlayableMediaRepository @Inject constructor( val mediaItem = getMediaItem(baseItem, playbackDecision) val resumePositionMs = calculateResumePosition(baseItem, playbackDecision.mediaSource) - val mediaTrackPreferences = trackPreferencesRepository.getMediaPreferences(baseItem.parentId.toString()).first() + val preferenceMediaId = when (baseItem.type) { + BaseItemKind.EPISODE -> baseItem.seriesId ?: mediaId + else -> mediaId + } + val mediaTrackPreferences = trackPreferencesRepository.getMediaPreferences(preferenceMediaId.toString()).first() val mediaSegments = getMediaSegments(mediaId) when (baseItem.type) { BaseItemKind.MOVIE -> PlayableMedia.Movie( id = mediaId, + preferenceMediaId = preferenceMediaId, mediaItem = mediaItem, resumePositionMs = resumePositionMs ?: 0L, preferences = mediaTrackPreferences, @@ -60,6 +65,7 @@ class DefaultPlayableMediaRepository @Inject constructor( ) BaseItemKind.SERIES -> PlayableMedia.Series( id = mediaId, + preferenceMediaId = preferenceMediaId, mediaItem = mediaItem, resumePositionMs = resumePositionMs ?: 0L, preferences = mediaTrackPreferences, @@ -67,6 +73,7 @@ class DefaultPlayableMediaRepository @Inject constructor( ) BaseItemKind.EPISODE -> PlayableMedia.Episode( id = mediaId, + preferenceMediaId = preferenceMediaId, mediaItem = mediaItem, resumePositionMs = resumePositionMs ?: 0L, preferences = mediaTrackPreferences,