diff --git a/app/src/main/java/org/mosad/teapod/ui/activity/player/PlayerActivity.kt b/app/src/main/java/org/mosad/teapod/ui/activity/player/PlayerActivity.kt index a1307d8..f3e2008 100644 --- a/app/src/main/java/org/mosad/teapod/ui/activity/player/PlayerActivity.kt +++ b/app/src/main/java/org/mosad/teapod/ui/activity/player/PlayerActivity.kt @@ -118,13 +118,13 @@ class PlayerActivity : AppCompatActivity() { override fun onNewIntent(intent: Intent?) { super.onNewIntent(intent) - // when the intent changed, lead the new media and play it + // when the intent changed, load the new media and play it intent?.let { model.loadMedia( it.getIntExtra(getString(R.string.intent_media_id), 0), it.getIntExtra(getString(R.string.intent_episode_id), 0) ) - model.playEpisode(model.currentEpisode, replace = true) + model.playEpisode(model.currentEpisode.mediaId, replace = true) } } @@ -206,14 +206,14 @@ class PlayerActivity : AppCompatActivity() { else -> View.VISIBLE } - if (state == ExoPlayer.STATE_ENDED && model.nextEpisode != null && Preferences.autoplay) { + if (state == ExoPlayer.STATE_ENDED && model.nextEpisodeId != null && Preferences.autoplay) { playNextEpisode() } } }) // start playing the current episode, after all needed player components have been initialized - model.playEpisode(model.currentEpisode, true) + model.playEpisode(model.currentEpisode.mediaId, true) } @SuppressLint("ClickableViewAccessibility") @@ -277,7 +277,7 @@ class PlayerActivity : AppCompatActivity() { // if remaining time < 20 sec, a next ep is set, autoplay is enabled and not in pip: // show next ep button if (remainingTime in 1..20000) { - if (!btnNextEpIsVisible && model.nextEpisode != null && Preferences.autoplay && !isInPiPMode()) { + if (!btnNextEpIsVisible && model.nextEpisodeId != null && Preferences.autoplay && !isInPiPMode()) { showButtonNextEp() } } else if (btnNextEpIsVisible) { @@ -335,7 +335,7 @@ class PlayerActivity : AppCompatActivity() { exo_text_title.text = model.getMediaTitle() // hide the next ep button, if there is none - button_next_ep_c.visibility = if (model.nextEpisode == null) { + button_next_ep_c.visibility = if (model.nextEpisodeId == null) { View.GONE } else { View.VISIBLE diff --git a/app/src/main/java/org/mosad/teapod/ui/activity/player/PlayerViewModel.kt b/app/src/main/java/org/mosad/teapod/ui/activity/player/PlayerViewModel.kt index 194110d..ca14e0f 100644 --- a/app/src/main/java/org/mosad/teapod/ui/activity/player/PlayerViewModel.kt +++ b/app/src/main/java/org/mosad/teapod/ui/activity/player/PlayerViewModel.kt @@ -29,9 +29,6 @@ import kotlin.collections.ArrayList * PlayerViewModel handles all stuff related to media/episodes. * When currentEpisode is changed the player will start playing it (not initial media), * the next episode will be update and the callback is handled. - * - * TODO rework don't use episodes for everything, use media instead - * this is a major rework of the AoDParser/Player/Media architecture */ class PlayerViewModel(application: Application) : AndroidViewModel(application) { @@ -44,16 +41,16 @@ class PlayerViewModel(application: Application) : AndroidViewModel(application) var media: AoDMedia = AoDMediaNone internal set - var currentEpisode = AoDEpisodeNone - internal set - var nextEpisode: AoDEpisode? = null + var mediaMeta: Meta? = null internal set var tmdbTVSeason: TMDBTVSeason? =null internal set - var mediaMeta: Meta? = null + var currentEpisode = AoDEpisodeNone internal set var currentEpisodeMeta: EpisodeMeta? = null internal set + var nextEpisodeId: Int? = null + internal set var currentLanguage: Locale = Locale.ROOT internal set @@ -97,7 +94,7 @@ class PlayerViewModel(application: Application) : AndroidViewModel(application) } currentEpisode = media.getEpisodeById(episodeId) - nextEpisode = selectNextEpisode() + nextEpisodeId = selectNextEpisode() currentEpisodeMeta = getEpisodeMetaByAoDMediaId(currentEpisode.mediaId) currentLanguage = currentEpisode.getPreferredStream(preferredLanguage).language } @@ -125,33 +122,37 @@ class PlayerViewModel(application: Application) : AndroidViewModel(application) /** * play the next episode, if nextEpisode is not null */ - fun playNextEpisode() = nextEpisode?.let { it -> + fun playNextEpisode() = nextEpisodeId?.let { it -> playEpisode(it, replace = true) } /** - * set currentEpisode to the param episode and start playing it - * update nextEpisode to reflect the change + * Set currentEpisode and start playing it. + * Update nextEpisode to reflect the change and update + * the watched state for the now playing episode. * - * updateWatchedState for the next (now current) episode + * @param episodeId The aod media id of the episode to play. + * @param replace (default = false) + * @param seekPosition The seek position for the episode (default = 0). */ - fun playEpisode(episode: AoDEpisode, replace: Boolean = false, seekPosition: Long = 0) { - val preferredStream = episode.getPreferredStream(currentLanguage) - currentLanguage = preferredStream.language // update current language, since it may have changed - currentEpisode = episode - nextEpisode = selectNextEpisode() - currentEpisodeMeta = getEpisodeMetaByAoDMediaId(episode.mediaId) - currentEpisodeChangedListener.forEach { it() } // update player gui (title) + fun playEpisode(episodeId: Int, replace: Boolean = false, seekPosition: Long = 0) { + currentEpisode = media.getEpisodeById(episodeId) + currentLanguage = currentEpisode.getPreferredStream(currentLanguage).language + currentEpisodeMeta = getEpisodeMetaByAoDMediaId(currentEpisode.mediaId) + nextEpisodeId = selectNextEpisode() + + // update player gui (title, next ep button) after nextEpisodeId has been set + currentEpisodeChangedListener.forEach { it() } val mediaSource = HlsMediaSource.Factory(dataSourceFactory).createMediaSource( - MediaItem.fromUri(Uri.parse(preferredStream.url)) + MediaItem.fromUri(Uri.parse(currentEpisode.getPreferredStream(currentLanguage).url)) ) playMedia(mediaSource, replace, seekPosition) // if episodes has not been watched, mark as watched - if (!episode.watched) { + if (!currentEpisode.watched) { viewModelScope.launch { - AoDParser.markAsWatched(media.aodId, episode.mediaId) + AoDParser.markAsWatched(media.aodId, currentEpisode.mediaId) } } } @@ -198,11 +199,13 @@ class PlayerViewModel(application: Application) : AndroidViewModel(application) } /** - * Based on the current episodeId, get the next episode. If there is no next - * episode, return null + * Based on the current episodes index, get the next episode. + * @return The next episode or null if there is none. */ - private fun selectNextEpisode(): AoDEpisode? { - return media.playlist.firstOrNull { it.index > media.getEpisodeById(currentEpisode.mediaId).index } + private fun selectNextEpisode(): Int? { + return media.playlist.firstOrNull { + it.index > media.getEpisodeById(currentEpisode.mediaId).index + }?.mediaId } } \ No newline at end of file diff --git a/app/src/main/java/org/mosad/teapod/ui/components/EpisodesListPlayer.kt b/app/src/main/java/org/mosad/teapod/ui/components/EpisodesListPlayer.kt index 9a7874d..13a6d40 100644 --- a/app/src/main/java/org/mosad/teapod/ui/components/EpisodesListPlayer.kt +++ b/app/src/main/java/org/mosad/teapod/ui/components/EpisodesListPlayer.kt @@ -31,7 +31,7 @@ class EpisodesListPlayer @JvmOverloads constructor( adapterRecEpisodes = PlayerEpisodeItemAdapter(model.media.playlist, model.tmdbTVSeason?.episodes) adapterRecEpisodes.onImageClick = { _, position -> (this.parent as ViewGroup).removeView(this) - model.playEpisode(model.media.playlist[position], replace = true) + model.playEpisode(model.media.playlist[position].mediaId, replace = true) } adapterRecEpisodes.currentSelected = model.currentEpisode.index