dev → main: Android UPnP/Sonos transport parity + server stream URL extension #79
+24
-3
@@ -53,6 +53,12 @@ class MinstrelForwardingPlayer(
|
|||||||
private val handler = Handler(delegate.applicationLooper)
|
private val handler = Handler(delegate.applicationLooper)
|
||||||
private var pollJob: Job? = null
|
private var pollJob: Job? = null
|
||||||
|
|
||||||
|
// Tracks consecutive non-PLAYING poll observations so a single transient
|
||||||
|
// PAUSED_PLAYBACK / STOPPED tick during a Sonos track transition does not
|
||||||
|
// flip the play/pause button. Manual pause still feels instant because it
|
||||||
|
// bypasses the poll entirely via applyTransportPaused().
|
||||||
|
@Volatile private var nonPlayingPollStreak = 0
|
||||||
|
|
||||||
init {
|
init {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
holder.active.collect { active -> onActiveChanged(active) }
|
holder.active.collect { active -> onActiveChanged(active) }
|
||||||
@@ -227,6 +233,7 @@ class MinstrelForwardingPlayer(
|
|||||||
|
|
||||||
private fun onActiveChanged(active: ActiveUpnp?) {
|
private fun onActiveChanged(active: ActiveUpnp?) {
|
||||||
pollJob?.cancel()
|
pollJob?.cancel()
|
||||||
|
nonPlayingPollStreak = 0
|
||||||
if (active != null) {
|
if (active != null) {
|
||||||
Timber.w("UPnP active: %s -- pollLoop starting", active.routeName)
|
Timber.w("UPnP active: %s -- pollLoop starting", active.routeName)
|
||||||
// Pause the wrapped ExoPlayer so we are not playing local audio
|
// Pause the wrapped ExoPlayer so we are not playing local audio
|
||||||
@@ -278,14 +285,28 @@ class MinstrelForwardingPlayer(
|
|||||||
)
|
)
|
||||||
val transport = active.avTransport.getTransportInfo()
|
val transport = active.avTransport.getTransportInfo()
|
||||||
when (transport.state) {
|
when (transport.state) {
|
||||||
TransportState.PLAYING -> remoteState.applyTransportPlaying()
|
TransportState.PLAYING -> {
|
||||||
TransportState.PAUSED -> remoteState.applyTransportPaused()
|
nonPlayingPollStreak = 0
|
||||||
TransportState.STOPPED -> remoteState.applyTransportStopped()
|
remoteState.applyTransportPlaying()
|
||||||
|
}
|
||||||
|
TransportState.PAUSED -> {
|
||||||
|
nonPlayingPollStreak += 1
|
||||||
|
if (nonPlayingPollStreak >= NON_PLAYING_CONFIRM) {
|
||||||
|
remoteState.applyTransportPaused()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TransportState.STOPPED -> {
|
||||||
|
nonPlayingPollStreak += 1
|
||||||
|
if (nonPlayingPollStreak >= NON_PLAYING_CONFIRM) {
|
||||||
|
remoteState.applyTransportStopped()
|
||||||
|
}
|
||||||
|
}
|
||||||
TransportState.TRANSITIONING, TransportState.UNKNOWN -> Unit
|
TransportState.TRANSITIONING, TransportState.UNKNOWN -> Unit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private companion object {
|
private companion object {
|
||||||
const val POLL_INTERVAL_MS = 1_000L
|
const val POLL_INTERVAL_MS = 1_000L
|
||||||
|
const val NON_PLAYING_CONFIRM = 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user