Files
pluriwave/openspec/changes/archive/2026-06-27-multi-device-eq/explore.md
T
FreeTLab bccc5c48b8
Build & Deploy PluriWave / Análisis de código (push) Successful in 38s
Build & Deploy PluriWave / Build APK + AAB release (push) Successful in 2m30s
docs(openspec): add SDD artifact trail for recent alarm and EQ changes
Persist the exploration, proposal, spec, design, tasks, and
verify/archive reports produced during the multi-device EQ,
alarm-countdown, and notification-visual-polish SDD cycles.
2026-07-04 12:42:11 +02:00

59 lines
2.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Exploration: Multi-Device Equalizer
## Current State
- Per-station EQ exists: `Map<String, PresetEcualizador>` in SharedPreferences keyed by station UUID
- No device detection or per-device EQ
- EQ is Android-only via `just_audio`'s `AndroidEqualizer`
- 3 existing platform channels in `MainActivity.kt` (visualizer, alarm, file_actions)
- `ServicioAudioSession` handles interruptions/becoming-noisy only — no device identity
## Key Findings
1. **EQ must be swapped in software** on device change — no native per-device EQ hook exists
2. **BT MAC available** via `AudioManager.getDevices()``AudioDeviceInfo.getAddress()` (API 23+). Does NOT require `BLUETOOTH_CONNECT` permission
3. **`_recrearPlayer()` resets AndroidEqualizer** on every source change — re-application must use device+station resolved preset
4. **iOS EQ is a no-op** but device tracking via `AVAudioSession.currentRoute` is possible
5. **No Flutter package covers this**`flutter_audio_output` is unmaintained, `audio_session` lacks device identity
## Recommended Approach
Custom platform channel `pluriwave/audio_devices` (Approach A):
- Android: `AudioManager.getDevices()` + `AudioDeviceCallback`
- iOS: `AVAudioSession.currentRoute` + `routeChangeNotification`
- Dart bridge: `ServicioDispositivoAudio` with `Stream<DispositivoAudio>` and `Future<List<DispositivoAudio>>`
## Resolution Hierarchy
```
1. presetsMatriz["stationUuid:deviceId"] ← station × device (most specific)
2. presetsEmisoraMap[stationUuid] ← station-only (existing)
3. presetsDispositivo[deviceId] ← device-only
4. presetPrincipal ← global default (existing)
```
## Persistence
New SharedPreferences keys (additive):
- `eq_multi_device_enabled_v1` → bool
- `eq_preset_por_dispositivo_v1` → JSON Map<deviceId, preset>
- `eq_presets_matriz_v1` → JSON Map<"stationUuid:deviceId", preset>
## Affected Files
| Area | Files |
|------|-------|
| Model | NEW `dispositivo_audio.dart` |
| Service | NEW `servicio_dispositivo_audio.dart`, extend `servicio_ecualizador.dart`, extend `servicio_audio.dart`, extend `servicio_export_import.dart` |
| State | Extend `estado_ecualizador.dart` |
| Native | Extend `MainActivity.kt`, NEW `AudioDevicesPlugin.swift` |
| UI | Extend `pantalla_ajustes.dart` |
| Tests | Extend existing + new test files |
## Risks
- Android minSdk must be ≥ 23 (likely already gated by AndroidEqualizer)
- iOS uid instability: use `portType+portName` as fallback key
- Backup v3 import must degrade gracefully in v2 builds
- Feature toggle OFF = zero regression invariant