dev → main: Android UPnP/Sonos transport parity + server stream URL extension #79
@@ -63,6 +63,7 @@ class PlayerController @Inject constructor(
|
|||||||
private val radio: RadioController,
|
private val radio: RadioController,
|
||||||
private val playerFactory: PlayerFactory,
|
private val playerFactory: PlayerFactory,
|
||||||
private val activeUpnpHolder: com.fabledsword.minstrel.player.output.ActiveUpnpHolder,
|
private val activeUpnpHolder: com.fabledsword.minstrel.player.output.ActiveUpnpHolder,
|
||||||
|
private val remoteState: RemotePlayerState,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -471,10 +472,31 @@ class PlayerController @Inject constructor(
|
|||||||
scope.launch(Dispatchers.Main.immediate) {
|
scope.launch(Dispatchers.Main.immediate) {
|
||||||
while (isActive) {
|
while (isActive) {
|
||||||
delay(POSITION_POLL_INTERVAL_MS)
|
delay(POSITION_POLL_INTERVAL_MS)
|
||||||
if (!controller.isPlaying) continue
|
// When UPnP is active, MediaController's cached state is stale --
|
||||||
uiStateInternal.value = uiStateInternal.value.copy(
|
// remoteState.applyTransportPlaying() doesn't fire a Player.Listener
|
||||||
positionMs = controller.currentPosition.coerceAtLeast(0),
|
// event, so onEvents never refreshes isPlaying / positionMs from
|
||||||
bufferedPositionMs = controller.bufferedPosition.coerceAtLeast(0),
|
// the wrapped player. Read directly from remoteState here so the
|
||||||
|
// play/pause toggle and scrubber reflect Sonos's actual state.
|
||||||
|
val upnpActive = activeUpnpHolder.active.value != null
|
||||||
|
val effectiveIsPlaying =
|
||||||
|
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 newBuf = controller.bufferedPosition.coerceAtLeast(0)
|
||||||
|
val changed = current.isPlaying != effectiveIsPlaying ||
|
||||||
|
current.positionMs != newPos ||
|
||||||
|
current.durationMs != newDur
|
||||||
|
if (!changed) continue
|
||||||
|
uiStateInternal.value = current.copy(
|
||||||
|
isPlaying = effectiveIsPlaying,
|
||||||
|
positionMs = newPos,
|
||||||
|
durationMs = newDur,
|
||||||
|
bufferedPositionMs = newBuf,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user