# Proposal: Multi-Device Equalizer ## Intent Users switching between audio outputs (BT headphones, wired headset, car stereo, built-in speaker) must manually re-adjust EQ every time. Each output has different frequency response characteristics, so a flat preset on one device sounds wrong on another. The app should remember per-device EQ preferences and swap them automatically on device change. ## Scope ### In Scope - Platform channel `pluriwave/audio_devices` (Android + iOS) for device detection and change events - Dart bridge `ServicioDispositivoAudio` with testable fake - 4-level EQ resolution: station+device > station > device > global - New SharedPreferences keys for device and matrix presets - Feature toggle (off by default) in Settings under "Advanced Equalization Options" - Export/import v3 with device-dimension fields - Copy current preset as starting point when a device is first seen ### Out of Scope - Per-station per-device UI (matrix editor) -- future phase - iOS EQ engine (no `just_audio` support; state tracked, application is no-op) - Audio device selection/routing (only detection, not forcing output) - Custom device naming or grouping ## Capabilities ### New Capabilities - `audio-device-detection`: Platform channel bridge for enumerating and streaming audio output device changes (Android AudioDeviceCallback, iOS AVAudioSession route notifications) - `multi-device-eq`: Device-aware EQ resolution, persistence of per-device and matrix presets, automatic preset swap on device change ### Modified Capabilities - `equalizer`: Resolution logic gains device dimension; `_recrearPlayer()` re-applies device-resolved preset instead of `_presetActual` - `export-import`: v3 schema adds `presetsPorDispositivo` and `presetsMatriz` fields with backward-compatible import ## Approach Custom platform channel (`pluriwave/audio_devices`) on both platforms, following the established pattern (alarm, visualizer, file_actions). `ServicioDispositivoAudio` exposes a `Stream` of device IDs. `EstadoEcualizador` subscribes and resolves via the 4-level hierarchy. Feature is gated by `eq_multi_device_enabled_v1` flag. ## Affected Areas | Area | Impact | Description | |------|--------|-------------| | `lib/servicios/servicio_dispositivo_audio.dart` | New | Dart platform channel bridge | | `lib/modelos/dispositivo_audio.dart` | New | Device value model | | `android/.../MainActivity.kt` | Modified | Add `pluriwave/audio_devices` channel | | `ios/Runner/AudioDevicesPlugin.swift` | New | iOS device detection | | `lib/servicios/servicio_ecualizador.dart` | Modified | New SP keys, device/matrix persistence | | `lib/estado/estado_ecualizador.dart` | Modified | 4-level resolution, device stream subscription | | `lib/servicios/servicio_audio.dart` | Modified | Expose current device ID | | `lib/servicios/servicio_export_import.dart` | Modified | v3 schema with device fields | | `lib/pantallas/pantalla_ajustes.dart` | Modified | Advanced EQ toggle + device preset list | | `test/estado/estado_ecualizador_test.dart` | Modified | Device-dimension test cases | | `test/helpers/fakes.dart` | Modified | FakeServicioDispositivoAudio | ## Risks | Risk | Likelihood | Mitigation | |------|------------|------------| | `_recrearPlayer()` resets EQ on source change | High | Re-apply device-resolved preset in `_activarEcualizador()` | | iOS BT device uid instability across restarts | Medium | Use `portType+portName` as fallback key | | v3 import in older app versions | Low | Null-safe handling; ignore unknown keys | | SharedPreferences size with large matrix | Low | ~20KB for 250 entries; well within limits | ## Rollback Plan 1. Feature toggle `eq_multi_device_enabled_v1` defaults to `false` -- disable returns to current behavior immediately 2. All new SP keys are independent; deleting them restores original EQ state 3. Export v3 is backward-compatible; v2 importers ignore new fields 4. Native channel can be removed without affecting existing channels 5. If critical issues arise, ship a patch setting the toggle to `false` and hiding the Settings section ## Dependencies - Android minSdk >= 23 (already required by `AndroidEqualizer`) - No new pub dependencies ## Success Criteria - [ ] Device change triggers automatic EQ preset swap within 500ms - [ ] Resolution hierarchy produces correct preset for all 4 levels - [ ] Feature toggle off: zero behavioral change from current release - [ ] Export/import round-trips device presets without data loss - [ ] All new logic covered by unit tests (Strict TDD) - [ ] No new permissions required on either platform