Convert state enum to sealed interface
This commit is contained in:
parent
e384669d85
commit
f8852856c6
|
@ -63,10 +63,10 @@ abstract class MessageVoiceBroadcastListeningItem : AbsMessageVoiceBroadcastItem
|
||||||
playPauseButton.setOnClickListener {
|
playPauseButton.setOnClickListener {
|
||||||
if (player.currentVoiceBroadcast == voiceBroadcast) {
|
if (player.currentVoiceBroadcast == voiceBroadcast) {
|
||||||
when (player.playingState) {
|
when (player.playingState) {
|
||||||
VoiceBroadcastPlayer.State.PLAYING,
|
VoiceBroadcastPlayer.State.Playing,
|
||||||
VoiceBroadcastPlayer.State.BUFFERING -> callback?.onTimelineItemAction(VoiceBroadcastAction.Listening.Pause)
|
VoiceBroadcastPlayer.State.Buffering -> callback?.onTimelineItemAction(VoiceBroadcastAction.Listening.Pause)
|
||||||
VoiceBroadcastPlayer.State.PAUSED,
|
VoiceBroadcastPlayer.State.Paused,
|
||||||
VoiceBroadcastPlayer.State.IDLE -> callback?.onTimelineItemAction(VoiceBroadcastAction.Listening.PlayOrResume(voiceBroadcast))
|
VoiceBroadcastPlayer.State.Idle -> callback?.onTimelineItemAction(VoiceBroadcastAction.Listening.PlayOrResume(voiceBroadcast))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
callback?.onTimelineItemAction(VoiceBroadcastAction.Listening.PlayOrResume(voiceBroadcast))
|
callback?.onTimelineItemAction(VoiceBroadcastAction.Listening.PlayOrResume(voiceBroadcast))
|
||||||
|
@ -100,17 +100,17 @@ abstract class MessageVoiceBroadcastListeningItem : AbsMessageVoiceBroadcastItem
|
||||||
|
|
||||||
private fun renderPlayingState(holder: Holder, state: VoiceBroadcastPlayer.State) {
|
private fun renderPlayingState(holder: Holder, state: VoiceBroadcastPlayer.State) {
|
||||||
with(holder) {
|
with(holder) {
|
||||||
bufferingView.isVisible = state == VoiceBroadcastPlayer.State.BUFFERING
|
bufferingView.isVisible = state == VoiceBroadcastPlayer.State.Buffering
|
||||||
voiceBroadcastMetadata.isVisible = state != VoiceBroadcastPlayer.State.BUFFERING
|
voiceBroadcastMetadata.isVisible = state != VoiceBroadcastPlayer.State.Buffering
|
||||||
|
|
||||||
when (state) {
|
when (state) {
|
||||||
VoiceBroadcastPlayer.State.PLAYING,
|
VoiceBroadcastPlayer.State.Playing,
|
||||||
VoiceBroadcastPlayer.State.BUFFERING -> {
|
VoiceBroadcastPlayer.State.Buffering -> {
|
||||||
playPauseButton.setImageResource(R.drawable.ic_play_pause_pause)
|
playPauseButton.setImageResource(R.drawable.ic_play_pause_pause)
|
||||||
playPauseButton.contentDescription = view.resources.getString(R.string.a11y_pause_voice_broadcast)
|
playPauseButton.contentDescription = view.resources.getString(R.string.a11y_pause_voice_broadcast)
|
||||||
}
|
}
|
||||||
VoiceBroadcastPlayer.State.IDLE,
|
VoiceBroadcastPlayer.State.Idle,
|
||||||
VoiceBroadcastPlayer.State.PAUSED -> {
|
VoiceBroadcastPlayer.State.Paused -> {
|
||||||
playPauseButton.setImageResource(R.drawable.ic_play_pause_play)
|
playPauseButton.setImageResource(R.drawable.ic_play_pause_play)
|
||||||
playPauseButton.contentDescription = view.resources.getString(R.string.a11y_play_voice_broadcast)
|
playPauseButton.contentDescription = view.resources.getString(R.string.a11y_play_voice_broadcast)
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ interface VoiceBroadcastPlayer {
|
||||||
val currentVoiceBroadcast: VoiceBroadcast?
|
val currentVoiceBroadcast: VoiceBroadcast?
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The current playing [State], [State.IDLE] by default.
|
* The current playing [State], [State.Idle] by default.
|
||||||
*/
|
*/
|
||||||
val playingState: State
|
val playingState: State
|
||||||
|
|
||||||
|
@ -68,11 +68,11 @@ interface VoiceBroadcastPlayer {
|
||||||
/**
|
/**
|
||||||
* Player states.
|
* Player states.
|
||||||
*/
|
*/
|
||||||
enum class State {
|
sealed interface State {
|
||||||
PLAYING,
|
object Playing : State
|
||||||
PAUSED,
|
object Paused : State
|
||||||
BUFFERING,
|
object Buffering : State
|
||||||
IDLE
|
object Idle : State
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -79,7 +79,7 @@ class VoiceBroadcastPlayerImpl @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override var playingState = State.IDLE
|
override var playingState: State = State.Idle
|
||||||
@MainThread
|
@MainThread
|
||||||
set(value) {
|
set(value) {
|
||||||
if (field != value) {
|
if (field != value) {
|
||||||
|
@ -96,7 +96,7 @@ class VoiceBroadcastPlayerImpl @Inject constructor(
|
||||||
val hasChanged = currentVoiceBroadcast != voiceBroadcast
|
val hasChanged = currentVoiceBroadcast != voiceBroadcast
|
||||||
when {
|
when {
|
||||||
hasChanged -> startPlayback(voiceBroadcast)
|
hasChanged -> startPlayback(voiceBroadcast)
|
||||||
playingState == State.PAUSED -> resumePlayback()
|
playingState == State.Paused -> resumePlayback()
|
||||||
else -> Unit
|
else -> Unit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -107,7 +107,7 @@ class VoiceBroadcastPlayerImpl @Inject constructor(
|
||||||
|
|
||||||
override fun stop() {
|
override fun stop() {
|
||||||
// Update state
|
// Update state
|
||||||
playingState = State.IDLE
|
playingState = State.Idle
|
||||||
|
|
||||||
// Stop and release media players
|
// Stop and release media players
|
||||||
stopPlayer()
|
stopPlayer()
|
||||||
|
@ -129,7 +129,7 @@ class VoiceBroadcastPlayerImpl @Inject constructor(
|
||||||
listeners[voiceBroadcast.voiceBroadcastId]?.add(listener) ?: run {
|
listeners[voiceBroadcast.voiceBroadcastId]?.add(listener) ?: run {
|
||||||
listeners[voiceBroadcast.voiceBroadcastId] = CopyOnWriteArrayList<Listener>().apply { add(listener) }
|
listeners[voiceBroadcast.voiceBroadcastId] = CopyOnWriteArrayList<Listener>().apply { add(listener) }
|
||||||
}
|
}
|
||||||
listener.onPlayingStateChanged(if (voiceBroadcast == currentVoiceBroadcast) playingState else State.IDLE)
|
listener.onPlayingStateChanged(if (voiceBroadcast == currentVoiceBroadcast) playingState else State.Idle)
|
||||||
listener.onLiveModeChanged(voiceBroadcast == currentVoiceBroadcast)
|
listener.onLiveModeChanged(voiceBroadcast == currentVoiceBroadcast)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,11 +139,11 @@ class VoiceBroadcastPlayerImpl @Inject constructor(
|
||||||
|
|
||||||
private fun startPlayback(voiceBroadcast: VoiceBroadcast) {
|
private fun startPlayback(voiceBroadcast: VoiceBroadcast) {
|
||||||
// Stop listening previous voice broadcast if any
|
// Stop listening previous voice broadcast if any
|
||||||
if (playingState != State.IDLE) stop()
|
if (playingState != State.Idle) stop()
|
||||||
|
|
||||||
currentVoiceBroadcast = voiceBroadcast
|
currentVoiceBroadcast = voiceBroadcast
|
||||||
|
|
||||||
playingState = State.BUFFERING
|
playingState = State.Buffering
|
||||||
|
|
||||||
observeVoiceBroadcastStateEvent(voiceBroadcast)
|
observeVoiceBroadcastStateEvent(voiceBroadcast)
|
||||||
}
|
}
|
||||||
|
@ -175,13 +175,13 @@ class VoiceBroadcastPlayerImpl @Inject constructor(
|
||||||
|
|
||||||
private fun onPlaylistUpdated() {
|
private fun onPlaylistUpdated() {
|
||||||
when (playingState) {
|
when (playingState) {
|
||||||
State.PLAYING,
|
State.Playing,
|
||||||
State.PAUSED -> {
|
State.Paused -> {
|
||||||
if (nextMediaPlayer == null && !isPreparingNextPlayer) {
|
if (nextMediaPlayer == null && !isPreparingNextPlayer) {
|
||||||
prepareNextMediaPlayer()
|
prepareNextMediaPlayer()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
State.BUFFERING -> {
|
State.Buffering -> {
|
||||||
val nextItem = if (isLiveListening && playlist.currentSequence == null) {
|
val nextItem = if (isLiveListening && playlist.currentSequence == null) {
|
||||||
// live listening, jump to the last item if playback has not started
|
// live listening, jump to the last item if playback has not started
|
||||||
playlist.lastOrNull()
|
playlist.lastOrNull()
|
||||||
|
@ -193,7 +193,7 @@ class VoiceBroadcastPlayerImpl @Inject constructor(
|
||||||
startPlayback(nextItem.startTime)
|
startPlayback(nextItem.startTime)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
State.IDLE -> Unit // Should not happen
|
State.Idle -> Unit // Should not happen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,7 +213,7 @@ class VoiceBroadcastPlayerImpl @Inject constructor(
|
||||||
if (sequencePosition > 0) {
|
if (sequencePosition > 0) {
|
||||||
mp.seekTo(sequencePosition)
|
mp.seekTo(sequencePosition)
|
||||||
}
|
}
|
||||||
playingState = State.PLAYING
|
playingState = State.Playing
|
||||||
prepareNextMediaPlayer()
|
prepareNextMediaPlayer()
|
||||||
}
|
}
|
||||||
} catch (failure: Throwable) {
|
} catch (failure: Throwable) {
|
||||||
|
@ -224,7 +224,7 @@ class VoiceBroadcastPlayerImpl @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun pausePlayback() {
|
private fun pausePlayback() {
|
||||||
playingState = State.PAUSED // This will trigger a playing state update and save the current position
|
playingState = State.Paused // This will trigger a playing state update and save the current position
|
||||||
if (currentMediaPlayer != null) {
|
if (currentMediaPlayer != null) {
|
||||||
currentMediaPlayer?.pause()
|
currentMediaPlayer?.pause()
|
||||||
} else {
|
} else {
|
||||||
|
@ -234,7 +234,7 @@ class VoiceBroadcastPlayerImpl @Inject constructor(
|
||||||
|
|
||||||
private fun resumePlayback() {
|
private fun resumePlayback() {
|
||||||
if (currentMediaPlayer != null) {
|
if (currentMediaPlayer != null) {
|
||||||
playingState = State.PLAYING
|
playingState = State.Playing
|
||||||
currentMediaPlayer?.start()
|
currentMediaPlayer?.start()
|
||||||
} else {
|
} else {
|
||||||
val savedPosition = currentVoiceBroadcast?.voiceBroadcastId?.let { playbackTracker.getPlaybackTime(it) } ?: 0
|
val savedPosition = currentVoiceBroadcast?.voiceBroadcastId?.let { playbackTracker.getPlaybackTime(it) } ?: 0
|
||||||
|
@ -247,11 +247,11 @@ class VoiceBroadcastPlayerImpl @Inject constructor(
|
||||||
voiceBroadcast != currentVoiceBroadcast -> {
|
voiceBroadcast != currentVoiceBroadcast -> {
|
||||||
playbackTracker.updatePausedAtPlaybackTime(voiceBroadcast.voiceBroadcastId, positionMillis, positionMillis.toFloat() / duration)
|
playbackTracker.updatePausedAtPlaybackTime(voiceBroadcast.voiceBroadcastId, positionMillis, positionMillis.toFloat() / duration)
|
||||||
}
|
}
|
||||||
playingState == State.PLAYING || playingState == State.BUFFERING -> {
|
playingState == State.Playing || playingState == State.Buffering -> {
|
||||||
updateLiveListeningMode(positionMillis)
|
updateLiveListeningMode(positionMillis)
|
||||||
startPlayback(positionMillis)
|
startPlayback(positionMillis)
|
||||||
}
|
}
|
||||||
playingState == State.IDLE || playingState == State.PAUSED -> {
|
playingState == State.Idle || playingState == State.Paused -> {
|
||||||
stopPlayer()
|
stopPlayer()
|
||||||
playbackTracker.updatePausedAtPlaybackTime(voiceBroadcast.voiceBroadcastId, positionMillis, positionMillis.toFloat() / duration)
|
playbackTracker.updatePausedAtPlaybackTime(voiceBroadcast.voiceBroadcastId, positionMillis, positionMillis.toFloat() / duration)
|
||||||
}
|
}
|
||||||
|
@ -267,15 +267,15 @@ class VoiceBroadcastPlayerImpl @Inject constructor(
|
||||||
isPreparingNextPlayer = false
|
isPreparingNextPlayer = false
|
||||||
nextMediaPlayer = mp
|
nextMediaPlayer = mp
|
||||||
when (playingState) {
|
when (playingState) {
|
||||||
State.PLAYING,
|
State.Playing,
|
||||||
State.PAUSED -> {
|
State.Paused -> {
|
||||||
currentMediaPlayer?.setNextMediaPlayer(mp)
|
currentMediaPlayer?.setNextMediaPlayer(mp)
|
||||||
}
|
}
|
||||||
State.BUFFERING -> {
|
State.Buffering -> {
|
||||||
mp.start()
|
mp.start()
|
||||||
onNextMediaPlayerStarted(mp)
|
onNextMediaPlayerStarted(mp)
|
||||||
}
|
}
|
||||||
State.IDLE -> stopPlayer()
|
State.Idle -> stopPlayer()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -327,10 +327,10 @@ class VoiceBroadcastPlayerImpl @Inject constructor(
|
||||||
currentVoiceBroadcast?.voiceBroadcastId?.let { voiceBroadcastId ->
|
currentVoiceBroadcast?.voiceBroadcastId?.let { voiceBroadcastId ->
|
||||||
// Start or stop playback ticker
|
// Start or stop playback ticker
|
||||||
when (playingState) {
|
when (playingState) {
|
||||||
State.PLAYING -> playbackTicker.startPlaybackTicker(voiceBroadcastId)
|
State.Playing -> playbackTicker.startPlaybackTicker(voiceBroadcastId)
|
||||||
State.PAUSED,
|
State.Paused,
|
||||||
State.BUFFERING,
|
State.Buffering,
|
||||||
State.IDLE -> playbackTicker.stopPlaybackTicker(voiceBroadcastId)
|
State.Idle -> playbackTicker.stopPlaybackTicker(voiceBroadcastId)
|
||||||
}
|
}
|
||||||
// Notify state change to all the listeners attached to the current voice broadcast id
|
// Notify state change to all the listeners attached to the current voice broadcast id
|
||||||
listeners[voiceBroadcastId]?.forEach { listener -> listener.onPlayingStateChanged(playingState) }
|
listeners[voiceBroadcastId]?.forEach { listener -> listener.onPlayingStateChanged(playingState) }
|
||||||
|
@ -348,7 +348,7 @@ class VoiceBroadcastPlayerImpl @Inject constructor(
|
||||||
// the current voice broadcast is not live (ended)
|
// the current voice broadcast is not live (ended)
|
||||||
mostRecentVoiceBroadcastEvent?.isLive != true -> false
|
mostRecentVoiceBroadcastEvent?.isLive != true -> false
|
||||||
// the player is stopped or paused
|
// the player is stopped or paused
|
||||||
playingState == State.IDLE || playingState == State.PAUSED -> false
|
playingState == State.Idle || playingState == State.Paused -> false
|
||||||
seekPosition != null -> {
|
seekPosition != null -> {
|
||||||
val seekDirection = seekPosition.compareTo(getCurrentPlaybackPosition() ?: 0)
|
val seekDirection = seekPosition.compareTo(getCurrentPlaybackPosition() ?: 0)
|
||||||
val newSequence = playlist.findByPosition(seekPosition)?.sequence
|
val newSequence = playlist.findByPosition(seekPosition)?.sequence
|
||||||
|
@ -374,13 +374,13 @@ class VoiceBroadcastPlayerImpl @Inject constructor(
|
||||||
|
|
||||||
private fun onLiveListeningChanged(isLiveListening: Boolean) {
|
private fun onLiveListeningChanged(isLiveListening: Boolean) {
|
||||||
// Live has ended and last chunk has been reached, we can stop the playback
|
// Live has ended and last chunk has been reached, we can stop the playback
|
||||||
if (!isLiveListening && playingState == State.BUFFERING && playlist.currentSequence == mostRecentVoiceBroadcastEvent?.content?.lastChunkSequence) {
|
if (!isLiveListening && playingState == State.Buffering && playlist.currentSequence == mostRecentVoiceBroadcastEvent?.content?.lastChunkSequence) {
|
||||||
stop()
|
stop()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onNextMediaPlayerStarted(mp: MediaPlayer) {
|
private fun onNextMediaPlayerStarted(mp: MediaPlayer) {
|
||||||
playingState = State.PLAYING
|
playingState = State.Playing
|
||||||
playlist.currentSequence = playlist.currentSequence?.inc()
|
playlist.currentSequence = playlist.currentSequence?.inc()
|
||||||
currentMediaPlayer = mp
|
currentMediaPlayer = mp
|
||||||
nextMediaPlayer = null
|
nextMediaPlayer = null
|
||||||
|
@ -427,7 +427,7 @@ class VoiceBroadcastPlayerImpl @Inject constructor(
|
||||||
stop()
|
stop()
|
||||||
} else {
|
} else {
|
||||||
// Enter in buffering mode and release current media player
|
// Enter in buffering mode and release current media player
|
||||||
playingState = State.BUFFERING
|
playingState = State.Buffering
|
||||||
currentMediaPlayer?.release()
|
currentMediaPlayer?.release()
|
||||||
currentMediaPlayer = null
|
currentMediaPlayer = null
|
||||||
}
|
}
|
||||||
|
@ -462,18 +462,18 @@ class VoiceBroadcastPlayerImpl @Inject constructor(
|
||||||
val playbackTime = getCurrentPlaybackPosition()
|
val playbackTime = getCurrentPlaybackPosition()
|
||||||
val percentage = getCurrentPlaybackPercentage()
|
val percentage = getCurrentPlaybackPercentage()
|
||||||
when (playingState) {
|
when (playingState) {
|
||||||
State.PLAYING -> {
|
State.Playing -> {
|
||||||
if (playbackTime != null && percentage != null) {
|
if (playbackTime != null && percentage != null) {
|
||||||
playbackTracker.updatePlayingAtPlaybackTime(id, playbackTime, percentage)
|
playbackTracker.updatePlayingAtPlaybackTime(id, playbackTime, percentage)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
State.PAUSED,
|
State.Paused,
|
||||||
State.BUFFERING -> {
|
State.Buffering -> {
|
||||||
if (playbackTime != null && percentage != null) {
|
if (playbackTime != null && percentage != null) {
|
||||||
playbackTracker.updatePausedAtPlaybackTime(id, playbackTime, percentage)
|
playbackTracker.updatePausedAtPlaybackTime(id, playbackTime, percentage)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
State.IDLE -> {
|
State.Idle -> {
|
||||||
if (playbackTime == null || percentage == null || (playlist.duration - playbackTime) < 50) {
|
if (playbackTime == null || percentage == null || (playlist.duration - playbackTime) < 50) {
|
||||||
playbackTracker.stopPlayback(id)
|
playbackTracker.stopPlayback(id)
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in New Issue