refactor(playback): share lost route pause transitions

This commit is contained in:
zarzet committed 2026-10-18 00:46:53 +07:00
1 parent e0dfa7eb69
commit dea131778c
2 files changed
+35 -9

No files matched your search

+9 -9
View File
@@ -334,6 +334,12 @@ class MusicPlaybackDeck {
if (!_disposed) _states.add(value);
}
void _pauseLostRoute(UsbAudioStatus status) {
_routeLost = true;
_setState(PlayerState.paused);
usbAudioStatus.value = status;
}
Future<void> resume() async {
if (!_direct) return _ordinary.resume();
if (_volumeBlocked) {
@@ -351,23 +357,17 @@ class MusicPlaybackDeck {
} on PlatformException {
if (token != _token || !_direct || _disposed) return;
if (_preparedStatus.driver == 'usb_direct') {
_routeLost = true;
_setState(PlayerState.paused);
usbAudioStatus.value = const UsbAudioStatus(reason: 'route_changed');
_pauseLostRoute(const UsbAudioStatus(reason: 'route_changed'));
throw UsbOutputUnavailable(
'Direct USB output changed; reconnect before playing',
);
}
if (_nativeStarted) {
_routeLost = true;
_setState(PlayerState.paused);
usbAudioStatus.value = const UsbAudioStatus(reason: 'route_changed');
_pauseLostRoute(const UsbAudioStatus(reason: 'route_changed'));
rethrow;
}
if (_preparedStatus.transport != 'pcm') {
_routeLost = true;
_setState(PlayerState.paused);
usbAudioStatus.value = const UsbAudioStatus(reason: 'dsd_unsupported');
_pauseLostRoute(const UsbAudioStatus(reason: 'dsd_unsupported'));
throw UsbDsdUnavailable();
}
final source = _source;
+26
View File
@@ -636,6 +636,23 @@ void main() {
expect(deck.needsSourceReload, isTrue);
});
test('failed first DoP start pauses without normal playback', () async {
transport = 'dop';
failResume = true;
await deck.setSource(
DeviceFileSource('/one.dsf'),
preferBitPerfect: true,
allowDop: true,
);
await expectLater(deck.resume(), throwsA(isA<UsbDsdUnavailable>()));
expect(deck.state, PlayerState.paused);
expect(deck.needsSourceReload, isTrue);
expect(usbAudioStatus.value.reason, 'dsd_unsupported');
expect(native.sources['usb-test'], isNull);
expect(native.playing, isEmpty);
expect(usbCalls, ['prepare', 'resume']);
});
test('DSD without a DAC never loads a normal audio source', () async {
fallbackReason = 'no_usb';
await expectLater(
@@ -743,6 +760,8 @@ void main() {
await expectLater(deck.resume(), throwsA(isA<UsbOutputUnavailable>()));
expect(native.sources['usb-test'], isNull);
expect(native.playing, isEmpty);
expect(deck.state, PlayerState.paused);
expect(deck.needsSourceReload, isTrue);
expect(usbAudioStatus.value.reason, 'route_changed');
},
);
@@ -755,14 +774,21 @@ void main() {
preferBitPerfect: true,
);
await deck.resume();
var statusChanges = 0;
void onStatusChanged() => statusChanges++;
usbAudioStatus.addListener(onStatusChanged);
addTearDown(() => usbAudioStatus.removeListener(onStatusChanged));
await event('paused');
await _until(() => deck.state == PlayerState.paused);
expect(native.playing, isEmpty);
expect(usbAudioStatus.value.reason, 'route_changed');
expect(statusChanges, 1);
position = 19000;
expect(deck.needsSourceReload, isTrue);
await expectLater(deck.resume(), throwsA(isA<PlatformException>()));
expect(native.playing, isEmpty);
expect(deck.state, PlayerState.paused);
expect(statusChanges, 1);
expect(await deck.getCurrentPosition(), const Duration(seconds: 19));
},
);