diff --git a/android/app/src/main/java/com/fabledsword/minstrel/player/PlayerController.kt b/android/app/src/main/java/com/fabledsword/minstrel/player/PlayerController.kt index 908b7e3e..15e3e7fa 100644 --- a/android/app/src/main/java/com/fabledsword/minstrel/player/PlayerController.kt +++ b/android/app/src/main/java/com/fabledsword/minstrel/player/PlayerController.kt @@ -61,6 +61,7 @@ class PlayerController @Inject constructor( @ApplicationScope private val scope: CoroutineScope, private val radio: RadioController, private val playerFactory: PlayerFactory, + private val activeUpnpHolder: com.fabledsword.minstrel.player.output.ActiveUpnpHolder, ) { /** @@ -321,6 +322,11 @@ class PlayerController @Inject constructor( * and advance past the dead track. Otherwise no-op. */ private fun handleZeroDurationIfNeeded(controller: MediaController, idx: Int) { + // Skip during UPnP playback. ExoPlayer is intentionally paused and never + // buffers tracks, so duration is permanently 0 / TIME_UNSET -- without + // this guard we rapid-advance through the entire local queue (and spam + // /api/playback-errors) every time the user activates a UPnP route. + if (activeUpnpHolder.active.value != null) return val current = queueRefs.getOrNull(idx) ?: return val duration = controller.duration val isZeroDuration = duration <= 0L || duration == androidx.media3.common.C.TIME_UNSET