diff --git a/core/model/src/main/java/hu/bbara/purefin/core/model/MediaSegment.kt b/core/model/src/main/java/hu/bbara/purefin/core/model/MediaSegment.kt index 30613540..1538c436 100644 --- a/core/model/src/main/java/hu/bbara/purefin/core/model/MediaSegment.kt +++ b/core/model/src/main/java/hu/bbara/purefin/core/model/MediaSegment.kt @@ -2,12 +2,17 @@ package hu.bbara.purefin.core.model import java.util.UUID -enum class SegmentType { - INTRO, - OUTRO, - MAIN_CONTENT, - PREVIEW, - RECAP; +enum class SegmentType(val value: Int) { + INTRO(0), + OUTRO(1), + MAIN_CONTENT(2), + PREVIEW(3), + RECAP(4); + + companion object { + fun fromValue(value: Int): SegmentType? = + entries.firstOrNull { it.value == value } + } } data class MediaSegment( diff --git a/core/player/src/main/java/hu/bbara/purefin/core/player/manager/MediaSegmentManager.kt b/core/player/src/main/java/hu/bbara/purefin/core/player/manager/MediaSegmentManager.kt new file mode 100644 index 00000000..4e51e41b --- /dev/null +++ b/core/player/src/main/java/hu/bbara/purefin/core/player/manager/MediaSegmentManager.kt @@ -0,0 +1,69 @@ +package hu.bbara.purefin.core.player.manager + +import android.os.Looper +import android.util.Log +import androidx.annotation.OptIn +import androidx.media3.common.util.UnstableApi +import androidx.media3.exoplayer.ExoPlayer +import androidx.media3.exoplayer.PlayerMessage +import hu.bbara.purefin.core.model.MediaSegment +import hu.bbara.purefin.core.model.SegmentType +import hu.bbara.purefin.core.player.model.SegmentStatus + +@OptIn(UnstableApi::class) +class MediaSegmentManager(private val player: ExoPlayer) { + + private var listener: MediaSegmentListener? = null + + interface MediaSegmentListener { + fun onEvent(segmentType: SegmentType, status: SegmentStatus) + } + + @Synchronized + fun registerListener(listener: MediaSegmentListener) { + this.listener?.let { + Log.w("PlayerMessageManager", "Listener was already register") + return + } + this.listener = listener + } + + fun addMediaSegments(mediaSegments: List) { + val messageTarget = PlayerMessage.Target { messageType, payload -> + SegmentType.fromValue(messageType)?.let { segmentType -> + notifyListener(segmentType, payload as SegmentStatus) + } + } + + mediaSegments.forEach { mediaSegment -> + installMediaSegment(messageTarget, mediaSegment) + } + + } + + private fun notifyListener(segmentType: SegmentType, status: SegmentStatus) { + if (listener == null) { + Log.w("PlayerMessageManager", "Listener was not register therefore it cannot notify") + } + listener?.onEvent(segmentType, status) + + } + + private fun installMediaSegment(messageTarget: PlayerMessage.Target, mediaSegment: MediaSegment) { + player.createMessage(messageTarget) + .setType(mediaSegment.type.value) + .setPosition(mediaSegment.startMs) + .setPayload(SegmentStatus.START) + .setLooper(Looper.getMainLooper()) + .setDeleteAfterDelivery(false) + .send() + + player.createMessage(messageTarget) + .setType(mediaSegment.type.value) + .setPayload(SegmentStatus.END) + .setPosition(mediaSegment.endMs) + .setLooper(Looper.getMainLooper()) + .setDeleteAfterDelivery(false) + .send() + } +} \ No newline at end of file diff --git a/core/player/src/main/java/hu/bbara/purefin/core/player/manager/PlayerManager.kt b/core/player/src/main/java/hu/bbara/purefin/core/player/manager/PlayerManager.kt index 28eff9c2..bf8a5457 100644 --- a/core/player/src/main/java/hu/bbara/purefin/core/player/manager/PlayerManager.kt +++ b/core/player/src/main/java/hu/bbara/purefin/core/player/manager/PlayerManager.kt @@ -7,8 +7,10 @@ import androidx.media3.common.PlaybackException import androidx.media3.common.Player import androidx.media3.common.TrackSelectionOverride import androidx.media3.common.util.UnstableApi +import androidx.media3.exoplayer.ExoPlayer import dagger.hilt.android.scopes.ViewModelScoped import hu.bbara.purefin.core.data.PlaybackReportContext +import hu.bbara.purefin.core.model.MediaSegment import hu.bbara.purefin.core.player.model.MediaContext import hu.bbara.purefin.core.player.model.MetadataState import hu.bbara.purefin.core.player.model.PlaybackProgressSnapshot @@ -51,6 +53,8 @@ class PlayerManager @Inject constructor( private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate) + private val mediaSegmentManager = MediaSegmentManager(player as ExoPlayer) + private var currentMediaContext: MediaContext? = null private var pendingSeekPositionMs: Long? = null @@ -84,10 +88,14 @@ class PlayerManager @Inject constructor( } } - override fun onEvents(player: Player, events: Player.Events) { - if (events.contains(Player.EVENT_MEDIA_ITEM_TRANSITION)) { - clearPendingSeek() + override fun onMediaItemTransition(mediaItem: MediaItem?, reason: Int) { + clearPendingSeek() + currentMediaContext?.let { + installMediaSegments(it.mediaSegments) } + } + + override fun onEvents(player: Player, events: Player.Events) { updateFromPlayer(player) if (events.contains(Player.EVENT_TRACKS_CHANGED)) { scope.launch { @@ -215,8 +223,10 @@ class PlayerManager @Inject constructor( } } - fun setPlaybackSpeed(speed: Float) { - player.setPlaybackSpeed(speed) + private fun installMediaSegments(mediaSegments: List) { + mediaSegmentManager.addMediaSegments( + mediaSegments = mediaSegments + ) } fun retry() { diff --git a/core/player/src/main/java/hu/bbara/purefin/core/player/model/SegmentStatus.kt b/core/player/src/main/java/hu/bbara/purefin/core/player/model/SegmentStatus.kt new file mode 100644 index 00000000..d5616b5d --- /dev/null +++ b/core/player/src/main/java/hu/bbara/purefin/core/player/model/SegmentStatus.kt @@ -0,0 +1,6 @@ +package hu.bbara.purefin.core.player.model + +enum class SegmentStatus { + START, + END +} \ No newline at end of file diff --git a/core/player/src/main/java/hu/bbara/purefin/core/player/viewmodel/PlayerViewModel.kt b/core/player/src/main/java/hu/bbara/purefin/core/player/viewmodel/PlayerViewModel.kt index c1b42218..a7408658 100644 --- a/core/player/src/main/java/hu/bbara/purefin/core/player/viewmodel/PlayerViewModel.kt +++ b/core/player/src/main/java/hu/bbara/purefin/core/player/viewmodel/PlayerViewModel.kt @@ -272,11 +272,6 @@ class PlayerViewModel @Inject constructor( playerManager.selectTrack(option) } - fun setPlaybackSpeed(speed: Float) { - playerManager.setPlaybackSpeed(speed) - _uiState.update { it.copy(playbackSpeed = speed) } - } - fun retry() { playerManager.retry() }