Post start, stop and progress of media to the server
This commit is contained in:
parent
e87a9804ec
commit
00ec736ff4
4 changed files with 68 additions and 1 deletions
|
@ -34,6 +34,7 @@ class JellyfinApi(context: Context, baseUrl: String) {
|
||||||
val sessionApi = SessionApi(api)
|
val sessionApi = SessionApi(api)
|
||||||
val videosApi = VideosApi(api)
|
val videosApi = VideosApi(api)
|
||||||
val mediaInfoApi = MediaInfoApi(api)
|
val mediaInfoApi = MediaInfoApi(api)
|
||||||
|
val playstateApi = PlayStateApi(api)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@Volatile
|
@Volatile
|
||||||
|
|
|
@ -19,4 +19,10 @@ interface JellyfinRepository {
|
||||||
suspend fun getMediaSources(itemId: UUID): List<MediaSourceInfo>
|
suspend fun getMediaSources(itemId: UUID): List<MediaSourceInfo>
|
||||||
|
|
||||||
suspend fun getStreamUrl(itemId: UUID, mediaSourceId: String): String
|
suspend fun getStreamUrl(itemId: UUID, mediaSourceId: String): String
|
||||||
|
|
||||||
|
suspend fun postPlaybackStart(itemId: UUID)
|
||||||
|
|
||||||
|
suspend fun postPlaybackStop(itemId: UUID, positionTicks: Long)
|
||||||
|
|
||||||
|
suspend fun postPlaybackProgress(itemId: UUID, positionTicks: Long, isPaused: Boolean)
|
||||||
}
|
}
|
|
@ -101,7 +101,7 @@ class JellyfinRepositoryImpl(private val jellyfinApi: JellyfinApi) : JellyfinRep
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun getStreamUrl(itemId: UUID, mediaSourceId: String): String {
|
override suspend fun getStreamUrl(itemId: UUID, mediaSourceId: String): String {
|
||||||
var streamUrl: String = ""
|
var streamUrl = ""
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
try {
|
try {
|
||||||
streamUrl = jellyfinApi.videosApi.getVideoStreamUrl(
|
streamUrl = jellyfinApi.videosApi.getVideoStreamUrl(
|
||||||
|
@ -115,4 +115,24 @@ class JellyfinRepositoryImpl(private val jellyfinApi: JellyfinApi) : JellyfinRep
|
||||||
}
|
}
|
||||||
return streamUrl
|
return streamUrl
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun postPlaybackStart(itemId: UUID) {
|
||||||
|
Log.d("PlayerActivity", "Sending start $itemId")
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
jellyfinApi.playstateApi.onPlaybackStart(jellyfinApi.userId!!, itemId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun postPlaybackStop(itemId: UUID, positionTicks: Long) {
|
||||||
|
Log.d("PlayerActivity", "Sending stop $itemId")
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
jellyfinApi.playstateApi.onPlaybackStopped(jellyfinApi.userId!!, itemId, positionTicks = positionTicks)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun postPlaybackProgress(itemId: UUID, positionTicks: Long, isPaused: Boolean) {
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
jellyfinApi.playstateApi.onPlaybackProgress(jellyfinApi.userId!!, itemId, positionTicks = positionTicks, isPaused = isPaused)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,8 @@
|
||||||
package dev.jdtech.jellyfin.viewmodels
|
package dev.jdtech.jellyfin.viewmodels
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.Looper
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
@ -11,6 +13,7 @@ import com.google.android.exoplayer2.trackselection.DefaultTrackSelector
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import dev.jdtech.jellyfin.repository.JellyfinRepository
|
import dev.jdtech.jellyfin.repository.JellyfinRepository
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@ -30,6 +33,8 @@ constructor(
|
||||||
private var playbackPosition: Long = 0
|
private var playbackPosition: Long = 0
|
||||||
private var _playbackStateListener: PlaybackStateListener
|
private var _playbackStateListener: PlaybackStateListener
|
||||||
|
|
||||||
|
private var itemId: UUID? = null
|
||||||
|
|
||||||
val playbackStateListener: PlaybackStateListener
|
val playbackStateListener: PlaybackStateListener
|
||||||
get() = _playbackStateListener
|
get() = _playbackStateListener
|
||||||
|
|
||||||
|
@ -38,6 +43,8 @@ constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
fun initializePlayer(itemId: UUID, mediaSourceId: String, playbackPosition: Long) {
|
fun initializePlayer(itemId: UUID, mediaSourceId: String, playbackPosition: Long) {
|
||||||
|
this.itemId = itemId
|
||||||
|
|
||||||
val renderersFactory =
|
val renderersFactory =
|
||||||
DefaultRenderersFactory(application).setExtensionRendererMode(DefaultRenderersFactory.EXTENSION_RENDERER_MODE_ON)
|
DefaultRenderersFactory(application).setExtensionRendererMode(DefaultRenderersFactory.EXTENSION_RENDERER_MODE_ON)
|
||||||
val trackSelector = DefaultTrackSelector(application)
|
val trackSelector = DefaultTrackSelector(application)
|
||||||
|
@ -62,10 +69,22 @@ constructor(
|
||||||
player.playWhenReady = playWhenReady
|
player.playWhenReady = playWhenReady
|
||||||
player.prepare()
|
player.prepare()
|
||||||
_player.value = player
|
_player.value = player
|
||||||
|
|
||||||
|
jellyfinRepository.postPlaybackStart(itemId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pollPosition(player, itemId)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun releasePlayer() {
|
private fun releasePlayer() {
|
||||||
|
itemId?.let { itemId ->
|
||||||
|
_player.value?.let { player ->
|
||||||
|
runBlocking {
|
||||||
|
jellyfinRepository.postPlaybackStop(itemId, player.currentPosition.times(10000))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (player.value != null) {
|
if (player.value != null) {
|
||||||
playWhenReady = player.value!!.playWhenReady
|
playWhenReady = player.value!!.playWhenReady
|
||||||
playbackPosition = player.value!!.currentPosition
|
playbackPosition = player.value!!.currentPosition
|
||||||
|
@ -76,6 +95,27 @@ constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun pollPosition(player: SimpleExoPlayer, itemId: UUID) {
|
||||||
|
val handler = Handler(Looper.getMainLooper())
|
||||||
|
val runnable: Runnable = object : Runnable {
|
||||||
|
override fun run() {
|
||||||
|
viewModelScope.launch {
|
||||||
|
Log.d(
|
||||||
|
"PlayerActivity",
|
||||||
|
"Posting progress of $itemId, position: ${player.currentPosition}"
|
||||||
|
)
|
||||||
|
jellyfinRepository.postPlaybackProgress(
|
||||||
|
itemId,
|
||||||
|
player.currentPosition.times(10000),
|
||||||
|
!player.isPlaying
|
||||||
|
)
|
||||||
|
}
|
||||||
|
handler.postDelayed(this, 2000)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
handler.post(runnable)
|
||||||
|
}
|
||||||
|
|
||||||
class PlaybackStateListener : Player.Listener {
|
class PlaybackStateListener : Player.Listener {
|
||||||
private val _navigateBack = MutableLiveData<Boolean>()
|
private val _navigateBack = MutableLiveData<Boolean>()
|
||||||
val navigateBack: LiveData<Boolean> = _navigateBack
|
val navigateBack: LiveData<Boolean> = _navigateBack
|
||||||
|
|
Loading…
Reference in a new issue