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 /
|
||||
// currentPosition all reflect that. Read from remoteState
|
||||
// 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
|
||||
uiStateInternal.value =
|
||||
PlayerUiState(
|
||||
@@ -448,11 +452,11 @@ class PlayerController @Inject constructor(
|
||||
} else {
|
||||
player.currentPosition
|
||||
}.coerceAtLeast(0),
|
||||
durationMs = if (upnpActive) {
|
||||
remoteState.durationMs
|
||||
} else {
|
||||
player.duration
|
||||
}.coerceAtLeast(0),
|
||||
durationMs = effectiveDuration(
|
||||
upnpActive,
|
||||
remoteState.durationMs,
|
||||
player.duration,
|
||||
),
|
||||
bufferedPositionMs = player.bufferedPosition.coerceAtLeast(0),
|
||||
playbackError = player.playerError?.message,
|
||||
currentSource = source,
|
||||
@@ -497,11 +501,13 @@ class PlayerController @Inject constructor(
|
||||
if (upnpActive) remoteState.isPlaying else controller.isPlaying
|
||||
val effectivePosition =
|
||||
if (upnpActive) remoteState.positionMs else controller.currentPosition
|
||||
val effectiveDuration =
|
||||
if (upnpActive) remoteState.durationMs else controller.duration
|
||||
val current = uiStateInternal.value
|
||||
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 changed = current.isPlaying != effectiveIsPlaying ||
|
||||
current.positionMs != newPos ||
|
||||
@@ -574,6 +580,18 @@ class PlayerController @Inject constructor(
|
||||
private fun sourceExtras(source: String): Bundle =
|
||||
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 {
|
||||
const val MINSTREL_SOURCE_KEY: String = "minstrel_source"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user