0416b301b2
- New ServicioExportImport owns the v2 backup envelope, pretty JSON encode and graceful decode; byte-compatible with existing exports, locked by a round-trip test - pantalla_ajustes delegates backup serialization to the service (inline jsonDecode/jsonEncode removed) - New EstadoEcualizador ChangeNotifier owns all EQ state and persistence (principal/current/per-station presets, active flag), exposed via its own provider so EQ changes no longer rebuild EstadoRadio consumers - EstadoRadio slims down ~210 lines and keeps 15 delegating compat members marked TODO(S4b) for the next slice to remove - Player EQ toggle rewired to the new provider to avoid going stale - 4 new tests (103 total green), flutter analyze clean
208 lines
6.3 KiB
Dart
208 lines
6.3 KiB
Dart
import 'package:flutter/foundation.dart';
|
|
|
|
import '../modelos/preset_ecualizador.dart';
|
|
import '../servicios/servicio_audio.dart';
|
|
import '../servicios/servicio_ecualizador.dart';
|
|
|
|
/// Equalizer state extracted from `EstadoRadio` (S4-R1).
|
|
///
|
|
/// Owns the main preset, the per-station preset map, the current (applied)
|
|
/// preset and the enabled flag, plus their persistence through
|
|
/// [ServicioEcualizador] and their application through [ServicioAudio].
|
|
/// Notifies ONLY its own listeners — EQ changes must not rebuild
|
|
/// `EstadoRadio` consumers (S4-R1-A, S4-R5).
|
|
class EstadoEcualizador extends ChangeNotifier {
|
|
EstadoEcualizador({
|
|
required this.audio,
|
|
ServicioEcualizador? servicio,
|
|
String? Function()? emisoraActualUuid,
|
|
}) : servicio = servicio ?? ServicioEcualizador(),
|
|
_emisoraActualUuid = emisoraActualUuid ?? (() => null);
|
|
|
|
final ServicioAudio audio;
|
|
final ServicioEcualizador servicio;
|
|
|
|
/// Callback into the owner (EstadoRadio) for the currently playing station;
|
|
/// keeps this notifier free of any station-list coupling.
|
|
final String? Function() _emisoraActualUuid;
|
|
|
|
final Map<String, PresetEcualizador> _presetsEmisoraMap = {};
|
|
PresetEcualizador _presetPrincipal = PresetEcualizador.flat;
|
|
PresetEcualizador _presetActual = PresetEcualizador.flat;
|
|
bool _activo = true;
|
|
|
|
PresetEcualizador get presetActual => _presetActual;
|
|
PresetEcualizador get presetPrincipal => _presetPrincipal;
|
|
bool get activo => _activo;
|
|
bool get disponible => audio.ecualizadorDisponible;
|
|
Map<String, PresetEcualizador> get presetsPorEmisora =>
|
|
Map.unmodifiable(_presetsEmisoraMap);
|
|
|
|
bool get emisoraActualTienePresetPropio {
|
|
final uuid = _emisoraActualUuid();
|
|
if (uuid == null) return false;
|
|
return tienePresetPorEmisora(uuid);
|
|
}
|
|
|
|
bool tienePresetPorEmisora(String uuid) =>
|
|
_presetsEmisoraMap.containsKey(uuid);
|
|
|
|
PresetEcualizador? presetPorEmisora(String uuid) => _presetsEmisoraMap[uuid];
|
|
|
|
PresetEcualizador presetParaEmisora(String uuid) =>
|
|
_presetsEmisoraMap[uuid] ?? _presetPrincipal;
|
|
|
|
/// Loads the persisted EQ configuration and applies it to the audio engine.
|
|
Future<void> cargarPersistido() async {
|
|
try {
|
|
final config = await servicio.cargar();
|
|
_presetPrincipal = config.principal;
|
|
_presetActual = config.principal;
|
|
_activo = config.activo;
|
|
_presetsEmisoraMap
|
|
..clear()
|
|
..addAll(config.porEmisora);
|
|
await audio.setEcualizadorActivo(_activo);
|
|
await audio.aplicarPreset(_presetPrincipal);
|
|
} catch (_) {
|
|
_presetPrincipal = PresetEcualizador.flat;
|
|
_presetActual = PresetEcualizador.flat;
|
|
_activo = true;
|
|
_presetsEmisoraMap.clear();
|
|
}
|
|
}
|
|
|
|
/// Applies [preset] to the audio engine and tracks it as current
|
|
/// WITHOUT persisting it (used when switching stations).
|
|
Future<void> aplicarPresetActivo(PresetEcualizador preset) async {
|
|
_presetActual = preset;
|
|
await audio.aplicarPreset(preset);
|
|
}
|
|
|
|
Future<void> cambiarPresetPrincipal(
|
|
PresetEcualizador preset, {
|
|
bool notificar = true,
|
|
}) async {
|
|
_presetPrincipal = preset;
|
|
await servicio.guardarPrincipal(preset);
|
|
|
|
final uuid = _emisoraActualUuid();
|
|
final puedeAplicarAhora =
|
|
uuid == null || !_presetsEmisoraMap.containsKey(uuid);
|
|
if (puedeAplicarAhora) {
|
|
await aplicarPresetActivo(preset);
|
|
}
|
|
|
|
if (notificar) notifyListeners();
|
|
}
|
|
|
|
Future<void> guardarPresetPorEmisora(
|
|
String uuid,
|
|
PresetEcualizador preset, {
|
|
bool notificar = true,
|
|
}) async {
|
|
_presetsEmisoraMap[uuid] = preset;
|
|
await servicio.guardarPorEmisora(uuid, preset);
|
|
if (_emisoraActualUuid() == uuid) {
|
|
await aplicarPresetActivo(preset);
|
|
}
|
|
if (notificar) notifyListeners();
|
|
}
|
|
|
|
Future<void> habilitarPresetPorEmisora(
|
|
String uuid, {
|
|
PresetEcualizador? base,
|
|
bool notificar = true,
|
|
}) async {
|
|
final presetBase = base ?? _presetsEmisoraMap[uuid] ?? _presetPrincipal;
|
|
await guardarPresetPorEmisora(uuid, presetBase, notificar: notificar);
|
|
}
|
|
|
|
Future<void> deshabilitarPresetPorEmisora(
|
|
String uuid, {
|
|
bool notificar = true,
|
|
}) async {
|
|
_presetsEmisoraMap.remove(uuid);
|
|
await servicio.eliminarPorEmisora(uuid);
|
|
if (_emisoraActualUuid() == uuid) {
|
|
await aplicarPresetActivo(_presetPrincipal);
|
|
}
|
|
if (notificar) notifyListeners();
|
|
}
|
|
|
|
Future<void> cambiarModoEmisoraActual({required bool usarPropio}) async {
|
|
final uuid = _emisoraActualUuid();
|
|
if (uuid == null) return;
|
|
if (usarPropio) {
|
|
await habilitarPresetPorEmisora(uuid);
|
|
} else {
|
|
await deshabilitarPresetPorEmisora(uuid);
|
|
}
|
|
}
|
|
|
|
Future<void> cambiarActivo(bool activo) async {
|
|
_activo = activo;
|
|
await servicio.guardarActivo(activo);
|
|
await audio.setEcualizadorActivo(activo);
|
|
if (activo) {
|
|
await audio.aplicarPreset(_presetActual);
|
|
}
|
|
notifyListeners();
|
|
}
|
|
|
|
Future<void> cambiarPreset(
|
|
PresetEcualizador preset, {
|
|
bool guardarPorEmisora = true,
|
|
}) async {
|
|
final uuid = _emisoraActualUuid();
|
|
final usarPresetPropio =
|
|
guardarPorEmisora &&
|
|
uuid != null &&
|
|
_presetsEmisoraMap.containsKey(uuid);
|
|
|
|
if (usarPresetPropio) {
|
|
await guardarPresetPorEmisora(uuid, preset);
|
|
return;
|
|
}
|
|
await cambiarPresetPrincipal(preset);
|
|
}
|
|
|
|
Future<void> cambiarBanda(int index, double db) async {
|
|
final bandas = List<double>.from(_presetActual.bandas);
|
|
if (index < 0 || index >= bandas.length) return;
|
|
|
|
bandas[index] = db;
|
|
final modificado = PresetEcualizador(
|
|
nombre: 'Personalizado',
|
|
bandas: bandas,
|
|
);
|
|
await cambiarPreset(modificado);
|
|
}
|
|
|
|
/// Replaces the whole EQ configuration (backup import path): persists it,
|
|
/// re-applies the preset effective for the current station and notifies.
|
|
Future<void> importarConfiguracion({
|
|
required PresetEcualizador principal,
|
|
required Map<String, PresetEcualizador> porEmisora,
|
|
}) async {
|
|
_presetPrincipal = principal;
|
|
_presetsEmisoraMap
|
|
..clear()
|
|
..addAll(porEmisora);
|
|
|
|
await servicio.guardarConfiguracion(
|
|
ConfiguracionEcualizador(
|
|
principal: _presetPrincipal,
|
|
porEmisora: _presetsEmisoraMap,
|
|
activo: _activo,
|
|
),
|
|
);
|
|
|
|
final uuid = _emisoraActualUuid();
|
|
await aplicarPresetActivo(
|
|
uuid == null ? _presetPrincipal : presetParaEmisora(uuid),
|
|
);
|
|
notifyListeners();
|
|
}
|
|
}
|