Player: add auto play next episode
This commit is contained in:
parent
353ae6937a
commit
23713fc1e6
|
@ -8,6 +8,7 @@ import android.util.Log
|
|||
import android.view.*
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.GestureDetectorCompat
|
||||
import androidx.core.view.isVisible
|
||||
import com.google.android.exoplayer2.ExoPlayer
|
||||
import com.google.android.exoplayer2.MediaItem
|
||||
import com.google.android.exoplayer2.Player
|
||||
|
@ -19,6 +20,7 @@ import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory
|
|||
import com.google.android.exoplayer2.util.Util
|
||||
import kotlinx.android.synthetic.main.activity_player.*
|
||||
import kotlinx.android.synthetic.main.player_controls.*
|
||||
import kotlinx.coroutines.*
|
||||
import org.mosad.teapod.parser.AoDParser
|
||||
import org.mosad.teapod.preferences.Preferences
|
||||
import org.mosad.teapod.util.DataTypes.MediaType
|
||||
|
@ -33,8 +35,6 @@ class PlayerActivity : AppCompatActivity() {
|
|||
private lateinit var controller: StyledPlayerControlView
|
||||
private lateinit var gestureDetector: GestureDetectorCompat
|
||||
|
||||
private var streamUrl = ""
|
||||
|
||||
private var mediaId = 0
|
||||
private var episodeId = 0
|
||||
|
||||
|
@ -119,19 +119,13 @@ class PlayerActivity : AppCompatActivity() {
|
|||
initExoPlayer()
|
||||
initVideoView()
|
||||
initController()
|
||||
initTimeUpdates()
|
||||
}
|
||||
|
||||
private fun initMedia() {
|
||||
media = AoDParser.getMediaById(mediaId)
|
||||
currentEpisode = media.episodes.first { it.id == episodeId }
|
||||
streamUrlFromEp(currentEpisode) // get current stream
|
||||
|
||||
// get next episode if present
|
||||
val nextEpIndex = media.episodes.indexOfFirst { it.id == episodeId } + 1
|
||||
if (nextEpIndex < (media.episodes.size - 1)) {
|
||||
println("has next episode")
|
||||
nextEpisode = media.episodes[nextEpIndex]
|
||||
}
|
||||
nextEpisode = selectNextEpisode()
|
||||
}
|
||||
|
||||
private fun initExoPlayer() {
|
||||
|
@ -140,7 +134,7 @@ class PlayerActivity : AppCompatActivity() {
|
|||
controller = video_view.findViewById(R.id.exo_controller)
|
||||
|
||||
val mediaSource = HlsMediaSource.Factory(dataSourceFactory)
|
||||
.createMediaSource(MediaItem.fromUri(Uri.parse(streamUrl)))
|
||||
.createMediaSource(MediaItem.fromUri(Uri.parse(selectStream(currentEpisode))))
|
||||
|
||||
player.playWhenReady = playWhenReady
|
||||
player.setMediaSource(mediaSource)
|
||||
|
@ -162,6 +156,11 @@ class PlayerActivity : AppCompatActivity() {
|
|||
View.VISIBLE -> View.INVISIBLE
|
||||
else -> View.VISIBLE
|
||||
}
|
||||
|
||||
if (state == ExoPlayer.STATE_ENDED && nextEpisode != null) {
|
||||
playNextEpisode()
|
||||
}
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -198,6 +197,7 @@ class PlayerActivity : AppCompatActivity() {
|
|||
} else {
|
||||
getString(R.string.time_hour_min_sec, hours, minutes, seconds)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
exo_text_title.text = currentEpisode.title // set media title
|
||||
|
@ -207,6 +207,26 @@ class PlayerActivity : AppCompatActivity() {
|
|||
exo_close_player.setOnClickListener { this.finish() }
|
||||
exo_rew_10.setOnClickListener { rewind() }
|
||||
exo_ffwd_10.setOnClickListener { forward() }
|
||||
button_next_ep.setOnClickListener { playNextEpisode() }
|
||||
}
|
||||
|
||||
private fun initTimeUpdates() = GlobalScope.launch {
|
||||
while (true) {
|
||||
val remainingTime = withContext(Dispatchers.Main) {
|
||||
player.duration - player.currentPosition
|
||||
}
|
||||
|
||||
if (remainingTime in 0..20000) {
|
||||
withContext(Dispatchers.Main) {
|
||||
// if the next ep button is not visible, make it visible
|
||||
if (!button_next_ep.isVisible) {
|
||||
button_next_ep.visibility = View.VISIBLE // TODO animation
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delay(1000)
|
||||
}
|
||||
}
|
||||
|
||||
private fun releasePlayer(){
|
||||
|
@ -226,11 +246,23 @@ class PlayerActivity : AppCompatActivity() {
|
|||
player.seekTo(player.currentPosition + fwdTime)
|
||||
}
|
||||
|
||||
@Suppress("unused")
|
||||
private fun playNextEpisode() {
|
||||
nextEpisode?.let { streamUrlFromEp(it) }
|
||||
// TODO play
|
||||
// TODO set next episode if present
|
||||
nextEpisode?.let { nextEp ->
|
||||
currentEpisode = nextEp // set current ep to next ep
|
||||
episodeId = nextEp.id
|
||||
|
||||
// update the gui
|
||||
exo_text_title.text = nextEp.title
|
||||
button_next_ep.visibility = View.GONE // TODO animation
|
||||
|
||||
player.clearMediaItems() //remove previous item
|
||||
val mediaSource = HlsMediaSource.Factory(dataSourceFactory)
|
||||
.createMediaSource(MediaItem.fromUri(Uri.parse(selectStream(nextEp))))
|
||||
player.setMediaSource(mediaSource)
|
||||
player.prepare()
|
||||
|
||||
nextEpisode = selectNextEpisode()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -238,18 +270,30 @@ class PlayerActivity : AppCompatActivity() {
|
|||
* use the secondary stream. Else, if the primary stream is set use the primary stream.
|
||||
* If no stream is present, close the activity.
|
||||
*/
|
||||
private fun streamUrlFromEp(episode: Episode) {
|
||||
streamUrl = if ((Preferences.preferSecondary || episode.priStreamUrl.isEmpty()) && episode.secStreamOmU) {
|
||||
private fun selectStream(episode: Episode): String {
|
||||
return if ((Preferences.preferSecondary || episode.priStreamUrl.isEmpty()) && episode.secStreamOmU) {
|
||||
episode.secStreamUrl
|
||||
} else if (episode.priStreamUrl.isNotEmpty()) {
|
||||
episode.priStreamUrl
|
||||
} else {
|
||||
Log.e(javaClass.name, "No stream url set.")
|
||||
this.finish()
|
||||
return
|
||||
""
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
|
|
@ -73,6 +73,7 @@ object AoDParser {
|
|||
|
||||
val resLogin = Jsoup.connect(baseUrl + loginPath)
|
||||
.method(Connection.Method.POST)
|
||||
.timeout(60000) // login can take some time
|
||||
.data(data)
|
||||
.postDataCharset("UTF-8")
|
||||
.cookies(authCookies)
|
||||
|
|
|
@ -17,7 +17,6 @@ import kotlinx.android.synthetic.main.fragment_media.*
|
|||
import org.mosad.teapod.MainActivity
|
||||
import org.mosad.teapod.R
|
||||
import org.mosad.teapod.parser.AoDParser
|
||||
import org.mosad.teapod.preferences.Preferences
|
||||
import org.mosad.teapod.util.DataTypes.MediaType
|
||||
import org.mosad.teapod.util.Episode
|
||||
import org.mosad.teapod.util.Media
|
||||
|
|
|
@ -24,6 +24,23 @@
|
|||
android:layout_width="70dp"
|
||||
android:layout_height="70dp"
|
||||
android:layout_gravity="center"
|
||||
app:indicatorColor="@color/exo_white"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/button_next_ep"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:layout_marginBottom="70dp"
|
||||
android:gravity="center"
|
||||
android:text="@string/next_episode"
|
||||
android:textAllCaps="false"
|
||||
android:textColor="@android:color/primary_text_light"
|
||||
android:textSize="16sp"
|
||||
android:visibility="gone"
|
||||
app:backgroundTint="@color/exo_white"
|
||||
app:iconGravity="textStart" />
|
||||
|
||||
</FrameLayout>
|
|
@ -35,6 +35,8 @@
|
|||
<string name="rewind_10">10 Sekunden zurück</string>
|
||||
<string name="play_pause">Abspielen/Pause</string>
|
||||
<string name="forward_10">10 Sekunden vorwärts</string>
|
||||
<string name="next_episode">Nächste Episode</string>
|
||||
|
||||
<!-- dialogs -->
|
||||
<string name="save">speichern</string>
|
||||
<string name="cancel">@android:string/cancel</string>
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
<string name="forward_10">forward 10 seconds</string>
|
||||
<string name="time_min_sec" translatable="false">%1$02d:%2$02d</string>
|
||||
<string name="time_hour_min_sec" translatable="false">%1$d:%2$02d:%3$02d</string>
|
||||
<string name="next_episode">Next Episode</string>
|
||||
|
||||
<!-- dialogs -->
|
||||
<string name="save">save</string>
|
||||
|
|
Loading…
Reference in New Issue