feat(eq): add per-device equalizer with 4-level preset resolution
Introduce multi-device EQ support allowing each audio output device (built-in speaker, wired, USB, individual Bluetooth by MAC) to have its own equalizer preset, combined with existing per-station presets for a full station×device matrix. - Add DispositivoAudio model and ServicioDispositivoAudio interface - Add Android platform channel (AudioDeviceCallback) for device detection - Add iOS AudioDevicesPlugin (AVAudioSession route tracking) - Extend ServicioEcualizador with device and matrix persistence keys - Implement 4-level resolution: matrix > station > device > global - Add advanced EQ settings section with feature toggle (off by default) - Extend export/import to v3 with backward compatibility - 184 tests passing, zero analyzer issues
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:pluriwave/modelos/dispositivo_audio.dart';
|
||||
|
||||
import '../helpers/fakes.dart';
|
||||
|
||||
void main() {
|
||||
group('ServicioDispositivoAudio (abstract contract)', () {
|
||||
late FakeServicioDispositivoAudio fake;
|
||||
|
||||
setUp(() {
|
||||
fake = FakeServicioDispositivoAudio();
|
||||
});
|
||||
|
||||
tearDown(() async {
|
||||
await fake.dispose();
|
||||
});
|
||||
|
||||
test('dispositivoActual is null initially', () {
|
||||
expect(fake.dispositivoActual, isNull);
|
||||
});
|
||||
|
||||
test(
|
||||
'obtenerDispositivoActual returns current device after emit',
|
||||
() async {
|
||||
const device = DispositivoAudio(
|
||||
id: 'builtin_speaker',
|
||||
tipo: TipoDispositivo.altavozInterno,
|
||||
nombre: 'Speaker',
|
||||
);
|
||||
fake.emitirDispositivo(device);
|
||||
|
||||
final result = await fake.obtenerDispositivoActual();
|
||||
expect(result, equals(device));
|
||||
},
|
||||
);
|
||||
|
||||
test('onDispositivoCambiado stream emits when device changes', () async {
|
||||
const deviceA = DispositivoAudio(
|
||||
id: 'builtin_speaker',
|
||||
tipo: TipoDispositivo.altavozInterno,
|
||||
nombre: 'Speaker',
|
||||
);
|
||||
const deviceB = DispositivoAudio(
|
||||
id: 'bt_a2dp:AA:BB:CC:DD:EE:FF',
|
||||
tipo: TipoDispositivo.bluetoothA2dp,
|
||||
nombre: 'BT Headphones',
|
||||
);
|
||||
|
||||
final received = <DispositivoAudio>[];
|
||||
final sub = fake.onDispositivoCambiado.listen(received.add);
|
||||
|
||||
fake.emitirDispositivo(deviceA);
|
||||
fake.emitirDispositivo(deviceB);
|
||||
|
||||
await Future<void>.delayed(Duration.zero);
|
||||
await sub.cancel();
|
||||
|
||||
expect(received, equals([deviceA, deviceB]));
|
||||
});
|
||||
|
||||
test('dispositivoActual tracks last emitted device', () {
|
||||
const device = DispositivoAudio(
|
||||
id: 'wired_headset',
|
||||
tipo: TipoDispositivo.auricularesCable,
|
||||
nombre: 'Wired Headset',
|
||||
);
|
||||
fake.emitirDispositivo(device);
|
||||
expect(fake.dispositivoActual, equals(device));
|
||||
});
|
||||
|
||||
test(
|
||||
'onDispositivoCambiado is a broadcast stream (multiple listeners)',
|
||||
() {
|
||||
expect(fake.onDispositivoCambiado.isBroadcast, isTrue);
|
||||
},
|
||||
);
|
||||
|
||||
test('dispose closes the stream without error', () async {
|
||||
await expectLater(fake.dispose(), completes);
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user