Player: load media async and use playhead for initial episode
This commit is contained in:
parent
287ef57bdb
commit
df4f43c0a2
@ -80,7 +80,7 @@ class PlayerActivity : AppCompatActivity() {
|
|||||||
setContentView(R.layout.activity_player)
|
setContentView(R.layout.activity_player)
|
||||||
hideBars() // Initial hide the bars
|
hideBars() // Initial hide the bars
|
||||||
|
|
||||||
model.loadMedia(
|
model.loadMediaAsync(
|
||||||
intent.getStringExtra(getString(R.string.intent_season_id)) ?: "",
|
intent.getStringExtra(getString(R.string.intent_season_id)) ?: "",
|
||||||
intent.getStringExtra(getString(R.string.intent_episode_id)) ?: ""
|
intent.getStringExtra(getString(R.string.intent_episode_id)) ?: ""
|
||||||
)
|
)
|
||||||
@ -143,7 +143,7 @@ class PlayerActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
// when the intent changed, load the new media and play it
|
// when the intent changed, load the new media and play it
|
||||||
intent?.let {
|
intent?.let {
|
||||||
model.loadMedia(
|
model.loadMediaAsync(
|
||||||
it.getStringExtra(getString(R.string.intent_season_id)) ?: "",
|
it.getStringExtra(getString(R.string.intent_season_id)) ?: "",
|
||||||
it.getStringExtra(getString(R.string.intent_episode_id)) ?: ""
|
it.getStringExtra(getString(R.string.intent_episode_id)) ?: ""
|
||||||
)
|
)
|
||||||
@ -194,11 +194,6 @@ class PlayerActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun initPlayer() {
|
private fun initPlayer() {
|
||||||
if (model.currentEpisode == NoneEpisode) {
|
|
||||||
Log.e(javaClass.name, "No media was set.")
|
|
||||||
this.finish()
|
|
||||||
}
|
|
||||||
|
|
||||||
initVideoView()
|
initVideoView()
|
||||||
initTimeUpdates()
|
initTimeUpdates()
|
||||||
|
|
||||||
@ -234,9 +229,10 @@ class PlayerActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// revert back to the old behaviour (blocking init) in case there are any issues with async init
|
||||||
// start playing the current episode, after all needed player components have been initialized
|
// start playing the current episode, after all needed player components have been initialized
|
||||||
model.playCurrentMedia()
|
//model.playCurrentMedia(model.currentPlayhead)
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("ClickableViewAccessibility")
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
@ -353,9 +349,16 @@ class PlayerActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* update title text and next ep button visibility, set ignoreNextStateEnded
|
* This methode is called, if the current episode has changed.
|
||||||
|
* Update title text and next ep button visibility.
|
||||||
|
* If the currentEpisode changed to NoneEpisode, exit the activity.
|
||||||
*/
|
*/
|
||||||
private fun onMediaChanged() {
|
private fun onMediaChanged() {
|
||||||
|
if (model.currentEpisode == NoneEpisode) {
|
||||||
|
Log.e(javaClass.name, "No media was set.")
|
||||||
|
this.finish()
|
||||||
|
}
|
||||||
|
|
||||||
exo_text_title.text = model.getMediaTitle()
|
exo_text_title.text = model.getMediaTitle()
|
||||||
|
|
||||||
// hide the next episode button, if there is none
|
// hide the next episode button, if there is none
|
||||||
|
@ -36,6 +36,8 @@ import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector
|
|||||||
import com.google.android.exoplayer2.source.hls.HlsMediaSource
|
import com.google.android.exoplayer2.source.hls.HlsMediaSource
|
||||||
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory
|
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory
|
||||||
import com.google.android.exoplayer2.util.Util
|
import com.google.android.exoplayer2.util.Util
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.joinAll
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import org.mosad.teapod.R
|
import org.mosad.teapod.R
|
||||||
@ -49,7 +51,6 @@ import org.mosad.teapod.util.Meta
|
|||||||
import org.mosad.teapod.util.TVShowMeta
|
import org.mosad.teapod.util.TVShowMeta
|
||||||
import org.mosad.teapod.util.tmdb.TMDBTVSeason
|
import org.mosad.teapod.util.tmdb.TMDBTVSeason
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.collections.ArrayList
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PlayerViewModel handles all stuff related to media/episodes.
|
* PlayerViewModel handles all stuff related to media/episodes.
|
||||||
@ -64,6 +65,7 @@ class PlayerViewModel(application: Application) : AndroidViewModel(application)
|
|||||||
|
|
||||||
val currentEpisodeChangedListener = ArrayList<() -> Unit>()
|
val currentEpisodeChangedListener = ArrayList<() -> Unit>()
|
||||||
private val preferredLanguage = if (Preferences.preferSecondary) Locale.JAPANESE else Locale.GERMAN
|
private val preferredLanguage = if (Preferences.preferSecondary) Locale.JAPANESE else Locale.GERMAN
|
||||||
|
private var currentPlayhead: Long = 0
|
||||||
|
|
||||||
// tmdb/meta data TODO currently not implemented for cr
|
// tmdb/meta data TODO currently not implemented for cr
|
||||||
var mediaMeta: Meta? = null
|
var mediaMeta: Meta? = null
|
||||||
@ -124,19 +126,11 @@ class PlayerViewModel(application: Application) : AndroidViewModel(application)
|
|||||||
mediaSession.isActive = true
|
mediaSession.isActive = true
|
||||||
}
|
}
|
||||||
|
|
||||||
fun loadMedia(seasonId: String, episodeId: String) {
|
fun loadMediaAsync(seasonId: String, episodeId: String) = viewModelScope.launch {
|
||||||
runBlocking {
|
episodes = Crunchyroll.episodes(seasonId)
|
||||||
episodes = Crunchyroll.episodes(seasonId)
|
|
||||||
//mediaMeta = loadMediaMeta(media.aodId) // can be done blocking, since it should be cached
|
|
||||||
|
|
||||||
// TODO replace this with setCurrentEpisode
|
setCurrentEpisode(episodeId)
|
||||||
currentEpisode = episodes.items.find { episode ->
|
playCurrentMedia(currentPlayhead)
|
||||||
episode.id == episodeId
|
|
||||||
} ?: NoneEpisode
|
|
||||||
println("loading playback ${currentEpisode.playback}")
|
|
||||||
|
|
||||||
currentPlayback = Crunchyroll.playback(currentEpisode.playback)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO reimplement for cr
|
// TODO reimplement for cr
|
||||||
// run async as it should be loaded by the time the episodes a
|
// run async as it should be loaded by the time the episodes a
|
||||||
@ -183,10 +177,23 @@ class PlayerViewModel(application: Application) : AndroidViewModel(application)
|
|||||||
episode.id == episodeId
|
episode.id == episodeId
|
||||||
} ?: NoneEpisode
|
} ?: NoneEpisode
|
||||||
|
|
||||||
// TODO don't run blocking
|
// update player gui (title, next ep button) after currentEpisode has changed
|
||||||
|
currentEpisodeChangedListener.forEach { it() }
|
||||||
|
|
||||||
|
// needs to be blocking, currentPlayback must be present when calling playCurrentMedia()
|
||||||
runBlocking {
|
runBlocking {
|
||||||
currentPlayback = Crunchyroll.playback(currentEpisode.playback)
|
joinAll(
|
||||||
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
|
currentPlayback = Crunchyroll.playback(currentEpisode.playback)
|
||||||
|
},
|
||||||
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
|
Crunchyroll.playheads(listOf(currentEpisode.id))[currentEpisode.id]?.let {
|
||||||
|
currentPlayhead = (it.playhead.times(1000)).toLong()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
println("loaded playback ${currentEpisode.playback}")
|
||||||
|
|
||||||
// TODO update metadata and language (it should not be needed to update the language here!)
|
// TODO update metadata and language (it should not be needed to update the language here!)
|
||||||
|
|
||||||
@ -201,9 +208,6 @@ class PlayerViewModel(application: Application) : AndroidViewModel(application)
|
|||||||
* @param seekPosition The seek position for the episode (default = 0).
|
* @param seekPosition The seek position for the episode (default = 0).
|
||||||
*/
|
*/
|
||||||
fun playCurrentMedia(seekPosition: Long = 0) {
|
fun playCurrentMedia(seekPosition: Long = 0) {
|
||||||
// update player gui (title, next ep button) after nextEpisodeId has been set
|
|
||||||
currentEpisodeChangedListener.forEach { it() }
|
|
||||||
|
|
||||||
// get preferred stream url, set current language if it differs from the preferred one
|
// get preferred stream url, set current language if it differs from the preferred one
|
||||||
val preferredLocale = currentLanguage
|
val preferredLocale = currentLanguage
|
||||||
val fallbackLocal = Locale.US
|
val fallbackLocal = Locale.US
|
||||||
|
Loading…
Reference in New Issue
Block a user