fix(android): duration falls back to local while Sonos hasn't reported one
android / Build + lint + test (push) Has been cancelled
android / Build + lint + test (push) Has been cancelled
This commit is contained in:
@@ -433,7 +433,11 @@ class PlayerController @Inject constructor(
|
|||||||
// no real audio loaded -- player.duration / isPlaying /
|
// no real audio loaded -- player.duration / isPlaying /
|
||||||
// currentPosition all reflect that. Read from remoteState
|
// currentPosition all reflect that. Read from remoteState
|
||||||
// instead so an onEvents fire (e.g. activity resume) doesn't
|
// instead so an onEvents fire (e.g. activity resume) doesn't
|
||||||
// clobber the UI with zeros.
|
// clobber the UI with zeros. Duration falls back to the
|
||||||
|
// wrapped player's value when Sonos hasn't reported one yet
|
||||||
|
// (pre-first-poll window, or Sonos still buffering) -- the
|
||||||
|
// wrapped ExoPlayer was prepared with the same MediaItem so
|
||||||
|
// it knows the real duration before any SOAP poll lands.
|
||||||
val upnpActive = activeUpnpHolder.active.value != null
|
val upnpActive = activeUpnpHolder.active.value != null
|
||||||
uiStateInternal.value =
|
uiStateInternal.value =
|
||||||
PlayerUiState(
|
PlayerUiState(
|
||||||
@@ -448,11 +452,11 @@ class PlayerController @Inject constructor(
|
|||||||
} else {
|
} else {
|
||||||
player.currentPosition
|
player.currentPosition
|
||||||
}.coerceAtLeast(0),
|
}.coerceAtLeast(0),
|
||||||
durationMs = if (upnpActive) {
|
durationMs = effectiveDuration(
|
||||||
remoteState.durationMs
|
upnpActive,
|
||||||
} else {
|
remoteState.durationMs,
|
||||||
player.duration
|
player.duration,
|
||||||
}.coerceAtLeast(0),
|
),
|
||||||
bufferedPositionMs = player.bufferedPosition.coerceAtLeast(0),
|
bufferedPositionMs = player.bufferedPosition.coerceAtLeast(0),
|
||||||
playbackError = player.playerError?.message,
|
playbackError = player.playerError?.message,
|
||||||
currentSource = source,
|
currentSource = source,
|
||||||
@@ -497,11 +501,13 @@ class PlayerController @Inject constructor(
|
|||||||
if (upnpActive) remoteState.isPlaying else controller.isPlaying
|
if (upnpActive) remoteState.isPlaying else controller.isPlaying
|
||||||
val effectivePosition =
|
val effectivePosition =
|
||||||
if (upnpActive) remoteState.positionMs else controller.currentPosition
|
if (upnpActive) remoteState.positionMs else controller.currentPosition
|
||||||
val effectiveDuration =
|
|
||||||
if (upnpActive) remoteState.durationMs else controller.duration
|
|
||||||
val current = uiStateInternal.value
|
val current = uiStateInternal.value
|
||||||
val newPos = effectivePosition.coerceAtLeast(0)
|
val newPos = effectivePosition.coerceAtLeast(0)
|
||||||
val newDur = effectiveDuration.coerceAtLeast(0)
|
val newDur = effectiveDuration(
|
||||||
|
upnpActive,
|
||||||
|
remoteState.durationMs,
|
||||||
|
controller.duration,
|
||||||
|
)
|
||||||
val newBuf = controller.bufferedPosition.coerceAtLeast(0)
|
val newBuf = controller.bufferedPosition.coerceAtLeast(0)
|
||||||
val changed = current.isPlaying != effectiveIsPlaying ||
|
val changed = current.isPlaying != effectiveIsPlaying ||
|
||||||
current.positionMs != newPos ||
|
current.positionMs != newPos ||
|
||||||
@@ -574,6 +580,18 @@ class PlayerController @Inject constructor(
|
|||||||
private fun sourceExtras(source: String): Bundle =
|
private fun sourceExtras(source: String): Bundle =
|
||||||
Bundle().apply { putString(MINSTREL_SOURCE_KEY, source) }
|
Bundle().apply { putString(MINSTREL_SOURCE_KEY, source) }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Duration to surface to the UI. When UPnP is active the remote's
|
||||||
|
* reported duration wins -- but if Sonos hasn't reported one yet
|
||||||
|
* (pre-first-poll window after activation, or transient 0 during a
|
||||||
|
* track-change buffer), fall back to the wrapped ExoPlayer's value
|
||||||
|
* for that MediaItem so the scrubber doesn't blink to zero.
|
||||||
|
*/
|
||||||
|
private fun effectiveDuration(upnpActive: Boolean, remoteMs: Long, localMs: Long): Long {
|
||||||
|
val pick = if (upnpActive && remoteMs > 0) remoteMs else localMs
|
||||||
|
return pick.coerceAtLeast(0)
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val MINSTREL_SOURCE_KEY: String = "minstrel_source"
|
const val MINSTREL_SOURCE_KEY: String = "minstrel_source"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user