fix(eq): re-apply equalizer when the native audio session rotates
ExoPlayer assigns a new audio session id after transient audio-focus interruptions (navigation prompts, radar warnings), leaving the AndroidEqualizer attached to the dead session so playback resumed without equalization until the next station switch. The session-id listener now detects genuine rotations through a dedicated guard and re-activates the equalizer with the current preset, gated on EQ availability to stay clear of player teardown/rebuild.
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
# Proposal: EQ Re-Apply After Audio-Focus Ducking
|
||||
|
||||
## Intent
|
||||
|
||||
When another app interrupts playback (Radarbot warnings, Google Maps directions), the native Android audio session id rotates on the audio-focus transition. ExoPlayer orphans the effect attached to the dead session (documented upstream, issue #5302), so `just_audio`'s `AndroidEqualizer` keeps its gain state but never re-pushes it to the new session. Music resumes flat/un-equalized. Re-attachment currently only fires on explicit station switch (`_cambiarFuente` -> `_activarEcualizador`, `servicio_audio.dart:449/526`). The user requires the music to ALWAYS stay equalized. This is Part B; disconnect-revert (Part A) is the separate `eq-device-disconnect-revert` change.
|
||||
|
||||
## Scope
|
||||
|
||||
### In Scope
|
||||
- Subscribe to `androidAudioSessionIdStream` inside `PluriWaveAudioHandler` for EQ purposes
|
||||
- On a changed + non-null session id, re-attach and re-push current gains via existing `_activarEcualizador()` / `aplicarPreset(_presetActual)`
|
||||
- Change-guard + `_eqDisponible` gate so it never re-fires redundantly nor races `_recrearPlayer()` teardown
|
||||
- New tests covering re-apply after session-id rotation, first-activation no-op, and teardown race
|
||||
|
||||
### Out of Scope
|
||||
- Part A device disconnect/cold-start revert (`eq-device-disconnect-revert`)
|
||||
- Any `ServicioAudioSession` interruption/duck/pause logic change
|
||||
- `EstadoEcualizador` / multi-device toggle logic
|
||||
- Kotlin/platform-channel changes
|
||||
- `VisualizadorAudio` (reference pattern only)
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
- `eq-audiofocus-reapply`: Equalizer re-attaches and re-applies current gains whenever the native audio session id rotates mid-playback
|
||||
|
||||
### Modified Capabilities
|
||||
- None (no existing equalizer spec)
|
||||
|
||||
## Approach
|
||||
|
||||
Extend the existing `_androidAudioSessionIdSub` listener (`servicio_audio.dart:258-265`), which today only stores/broadcasts the id. After broadcast, if the id changed and is non-null AND `_eqDisponible` is true, call the idempotent choke-point to re-enable and re-write band gains for `_presetActual`. This mirrors `VisualizadorAudio._onSessionId` (`visualizador_audio.dart:82-88`) — the proven in-repo reaction pattern. The fix lives entirely below the multi-device layer (`_eqMultiDeviceEnabled` is an `EstadoEcualizador` concern, absent from this file), so it applies regardless of that toggle.
|
||||
|
||||
## Affected Areas
|
||||
|
||||
| Area | Impact | Description |
|
||||
|------|--------|-------------|
|
||||
| `lib/servicios/servicio_audio.dart` | Modified | Add EQ re-apply to `_androidAudioSessionIdSub` listener |
|
||||
| `test/servicios/` | New | Session-id rotation re-apply + guard/race coverage |
|
||||
|
||||
## Risks
|
||||
|
||||
| Risk | Likelihood | Mitigation |
|
||||
|------|------------|------------|
|
||||
| Redundant re-fire on first/legit activation | Med | Change-guard (`== _lastSessionId` return), mirrors visualizer |
|
||||
| Race with `_recrearPlayer()` rebuild | Med | Gate on `_eqDisponible == true`; teardown sets it false + nulls id |
|
||||
| Regress station-switch / manual slider path | Low | Different call sites unchanged; full `flutter test` regression |
|
||||
|
||||
## Rollback Plan
|
||||
|
||||
Change is a self-contained addition to one listener block plus new tests. Revert the commit to restore prior (broken) behavior — no persistence, schema, or API surface change, so no data migration or downstream impact.
|
||||
|
||||
## Dependencies
|
||||
|
||||
- None. `androidAudioSessionIdStream`, `_activarEcualizador()`, `aplicarPreset()` all already exist.
|
||||
|
||||
## Success Criteria
|
||||
|
||||
- [ ] After another app ducks/interrupts playback, resumed music stays equalized
|
||||
- [ ] EQ re-applies on every changed non-null session id, regardless of `_eqMultiDeviceEnabled`
|
||||
- [ ] No redundant re-apply on first activation or during `_recrearPlayer()` teardown
|
||||
- [ ] Station-switch and manual slider (`setBanda`) paths unchanged
|
||||
- [ ] All new behavior covered by passing tests (Strict TDD)
|
||||
Reference in New Issue
Block a user