Two regressions ride together when gapless plays a chain of more than
two tracks:
- The pos/dur snapshot at the top of the audio-thread iteration is
captured BEFORE the gapless transition swap. After the swap
updates current_track_id and duration, the local pos/dur still
point at the outgoing track, and the "approaching end" check a
few lines below fires immediately for the new track with stale
299/299-style values.
- That spurious firing arms gapless_request_armed=true and sets
gapless_ready=true. gapless_request_armed only gets cleared again
on a future transition (which will never happen because the new
track has no prefetch queued) or on engine empty (i.e. when
playback has already stopped). gapless_ready also stays sticky-
true because nothing else clears it once the false-positive fires.
- End result: the new track plays through with the gate stuck
closed, the real "approaching end" check at ~T-10s never fires,
the frontend never gets prompted to call play_next_gapless for
track #N+1, and the audio thread reaches engine empty and stops.
Fix:
- Track whether a transition swap consumed pending in this
iteration via a local transition_consumed_pending bool. Skip the
"approaching end" check while that flag is set — the next
iteration will run with fresh pos/dur for the new track and
fire the trigger correctly.
- Reset gapless_ready=false in both transition swap paths
(mainline and ALSA Direct), mirroring the existing
gapless_request_armed=false reset, so neither flag survives a
transition.
cc