diff --git a/app/src/main/java/org/mosad/teapod/PlayerActivity.kt b/app/src/main/java/org/mosad/teapod/PlayerActivity.kt index 54948d4..b04f2ac 100644 --- a/app/src/main/java/org/mosad/teapod/PlayerActivity.kt +++ b/app/src/main/java/org/mosad/teapod/PlayerActivity.kt @@ -8,6 +8,7 @@ import android.os.Build import android.os.Bundle import android.util.Log import android.view.* +import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity import androidx.core.view.GestureDetectorCompat import androidx.core.view.isVisible @@ -26,12 +27,9 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -import org.mosad.teapod.parser.AoDParser +import org.mosad.teapod.player.PlayerViewModel import org.mosad.teapod.preferences.Preferences -import org.mosad.teapod.ui.fragments.MediaFragment -import org.mosad.teapod.util.DataTypes.MediaType import org.mosad.teapod.util.Episode -import org.mosad.teapod.util.Media import java.util.* import java.util.concurrent.TimeUnit import kotlin.concurrent.scheduleAtFixedRate @@ -44,12 +42,7 @@ class PlayerActivity : AppCompatActivity() { private lateinit var gestureDetector: GestureDetectorCompat private lateinit var timerUpdates: TimerTask - private var mediaId = 0 - private var episodeId = 0 - - private var media: Media = Media(0, "", MediaType.OTHER) - private var currentEpisode = Episode() - private var nextEpisode: Episode? = null + private val model: PlayerViewModel by viewModels() private var playWhenReady = true private var currentWindow = 0 @@ -70,8 +63,10 @@ class PlayerActivity : AppCompatActivity() { playWhenReady = it.getBoolean(getString(R.string.state_is_playing)) } - mediaId = intent.getIntExtra(getString(R.string.intent_media_id), 0) - episodeId = intent.getIntExtra(getString(R.string.intent_episode_id), 0) + model.loadMedia( + intent.getIntExtra(getString(R.string.intent_media_id), 0), + intent.getIntExtra(getString(R.string.intent_episode_id), 0) + ) gestureDetector = GestureDetectorCompat(this, PlayerGestureListener()) @@ -119,30 +114,23 @@ class PlayerActivity : AppCompatActivity() { } private fun initPlayer() { - if (mediaId <= 0) { + if (model.mediaId <= 0) { Log.e(javaClass.name, "No media id was set.") this.finish() } - initMedia() initExoPlayer() initVideoView() initTimeUpdates() } - private fun initMedia() { - media = AoDParser.getMediaById(mediaId) - currentEpisode = media.episodes.first { it.id == episodeId } - nextEpisode = selectNextEpisode() - } - private fun initExoPlayer() { player = SimpleExoPlayer.Builder(this).build() dataSourceFactory = DefaultDataSourceFactory(this, Util.getUserAgent(this, "Teapod")) controller = video_view.findViewById(R.id.exo_controller) val mediaSource = HlsMediaSource.Factory(dataSourceFactory) - .createMediaSource(MediaItem.fromUri(Uri.parse(autoSelectStream(currentEpisode)))) + .createMediaSource(MediaItem.fromUri(Uri.parse(autoSelectStream(model.currentEpisode)))) player.playWhenReady = playWhenReady player.setMediaSource(mediaSource) @@ -165,7 +153,7 @@ class PlayerActivity : AppCompatActivity() { else -> View.VISIBLE } - if (state == ExoPlayer.STATE_ENDED && nextEpisode != null && Preferences.autoplay) { + if (state == ExoPlayer.STATE_ENDED && model.nextEpisode != null && Preferences.autoplay) { playNextEpisode() } @@ -173,7 +161,7 @@ class PlayerActivity : AppCompatActivity() { }) controller.isAnimationEnabled = false // disable controls (time-bar) animation - exo_text_title.text = currentEpisode.title // set media title + exo_text_title.text = model.currentEpisode.title // set media title } @SuppressLint("ClickableViewAccessibility") @@ -221,7 +209,7 @@ class PlayerActivity : AppCompatActivity() { if (remainingTime in 1..20000) { // if the next ep button is not visible, make it visible - if (!btnNextEpIsVisible && nextEpisode != null && Preferences.autoplay) { + if (!btnNextEpIsVisible && model.nextEpisode != null && Preferences.autoplay) { withContext(Dispatchers.Main) { showButtonNextEp() } } } else if (btnNextEpIsVisible) { @@ -311,7 +299,7 @@ class PlayerActivity : AppCompatActivity() { } } - private fun playNextEpisode() = nextEpisode?.let { nextEp -> + private fun playNextEpisode() = model.nextEpisode?.let { nextEp -> // update the gui exo_text_title.text = nextEp.title hideButtonNextEp() @@ -322,12 +310,7 @@ class PlayerActivity : AppCompatActivity() { player.setMediaSource(mediaSource) player.prepare() - // watchedCallback for next ep - currentEpisode = nextEp // set current ep to next ep - episodeId = nextEp.id - MediaFragment.instance.updateWatchedState(nextEp) - - nextEpisode = selectNextEpisode() + model.nextEpisode() } /** @@ -347,19 +330,6 @@ class PlayerActivity : AppCompatActivity() { } } - /** - * Based on the current episodeId, get the next episode. If there is no next - * episode, return null - */ - private fun selectNextEpisode(): Episode? { - val nextEpIndex = media.episodes.indexOfFirst { it.id == currentEpisode.id } + 1 - return if (nextEpIndex < (media.episodes.size)) { - media.episodes[nextEpIndex] - } else { - null - } - } - /** * hide the status and navigation bar */ diff --git a/app/src/main/java/org/mosad/teapod/player/PlayerViewModel.kt b/app/src/main/java/org/mosad/teapod/player/PlayerViewModel.kt new file mode 100644 index 0000000..45bafd2 --- /dev/null +++ b/app/src/main/java/org/mosad/teapod/player/PlayerViewModel.kt @@ -0,0 +1,58 @@ +package org.mosad.teapod.player + +import androidx.lifecycle.ViewModel +import org.mosad.teapod.parser.AoDParser +import org.mosad.teapod.ui.fragments.MediaFragment +import org.mosad.teapod.util.DataTypes +import org.mosad.teapod.util.Episode +import org.mosad.teapod.util.Media + +class PlayerViewModel : ViewModel() { + + var mediaId = 0 + internal set + var episodeId = 0 + internal set + + var media: Media = Media(0, "", DataTypes.MediaType.OTHER) + internal set + var currentEpisode = Episode() + internal set + var nextEpisode: Episode? = null + internal set + + fun loadMedia(iMediaId: Int, iEpisodeId: Int) { + mediaId = iMediaId + episodeId = iEpisodeId + + media = AoDParser.getMediaById(mediaId) + currentEpisode = media.episodes.first { it.id == episodeId } + nextEpisode = selectNextEpisode() + } + + /** + * update currentEpisode, episodeId, nextEpisode to new episode + * updateWatchedState for the next (now current) episode + */ + fun nextEpisode() = nextEpisode?.let { nextEp -> + currentEpisode = nextEp // set current ep to next ep + episodeId = nextEp.id + MediaFragment.instance.updateWatchedState(nextEp) // watchedCallback for next ep + + nextEpisode = selectNextEpisode() + } + + /** + * Based on the current episodeId, get the next episode. If there is no next + * episode, return null + */ + private fun selectNextEpisode(): Episode? { + val nextEpIndex = media.episodes.indexOfFirst { it.id == currentEpisode.id } + 1 + return if (nextEpIndex < (media.episodes.size)) { + media.episodes[nextEpIndex] + } else { + null + } + } + +} \ No newline at end of file