Better handling of sequential platform activations/deactivations.

This commit is contained in:
Ryan Heise 2020-12-26 20:33:31 +11:00
parent 4cab031d30
commit 9ab7d8b210
4 changed files with 681 additions and 679 deletions

View File

@ -32,7 +32,7 @@ Please consider reporting any bugs you encounter [here](https://github.com/ryanh
`load()` and `stop()` have new behaviours in 0.6.x documented [here](https://pub.dev/documentation/just_audio/latest/just_audio/AudioPlayer-class.html) that provide greater flexibility in how system resources are acquired and released. For a quick migration that maintains 0.5.x behaviour: `load()` and `stop()` have new behaviours in 0.6.x documented [here](https://pub.dev/documentation/just_audio/latest/just_audio/AudioPlayer-class.html) that provide greater flexibility in how system resources are acquired and released. For a quick migration that maintains 0.5.x behaviour:
* Replace `await player.load(source);` by `await player.setAudioSource(source);` * Replace `await player.load(source);` by `await player.setAudioSource(source);`
* Replace `await stop();` by `await player.pause(); await player.seek(Duration.zero); * Replace `await stop();` by `await player.pause(); await player.seek(Duration.zero);`
Also beware that `playbackEventStream` will now emit events strictly when the fields in `PlaybackEvent` change. In 0.5.x this often (by chance) coincided with `playing` state changes. Apps that depended on this behaviour will break in 0.6.x and should explicitly listen for `playing` state changes via `playingStream` or `playerStateStream`. Also beware that `playbackEventStream` will now emit events strictly when the fields in `PlaybackEvent` change. In 0.5.x this often (by chance) coincided with `playing` state changes. Apps that depended on this behaviour will break in 0.6.x and should explicitly listen for `playing` state changes via `playingStream` or `playerStateStream`.

View File

@ -542,18 +542,14 @@ class AudioPlayer {
_playbackEventSubject.add(_playbackEvent = PlaybackEvent( _playbackEventSubject.add(_playbackEvent = PlaybackEvent(
currentIndex: initialIndex, updatePosition: initialPosition)); currentIndex: initialIndex, updatePosition: initialPosition));
_broadcastSequence(); _broadcastSequence();
// TODO: If the active platform existed, we should try to retain it.
try {
await _setPlatformActive(false);
} catch (e) {
print("Error deactivating previous platform: $e (ignoring)");
}
_audioSource = source; _audioSource = source;
_broadcastSequence(); _broadcastSequence();
Duration duration; Duration duration;
if (playing) preload = true; if (playing) preload = true;
if (preload) { if (preload) {
duration = await load(); duration = await load();
} else {
await _setPlatformActive(false);
} }
return duration; return duration;
} }
@ -573,8 +569,14 @@ class AudioPlayer {
if (_audioSource == null) { if (_audioSource == null) {
throw Exception('Must set AudioSource before loading'); throw Exception('Must set AudioSource before loading');
} }
if (_active) {
return await _load(await _platform, _audioSource,
initialSeekValues: _initialSeekValues);
} else {
// This will implicitly load the current audio source.
return await _setPlatformActive(true); return await _setPlatformActive(true);
} }
}
void _broadcastSequence() { void _broadcastSequence() {
_sequenceSubject.add(_audioSource?.sequence); _sequenceSubject.add(_audioSource?.sequence);
@ -601,7 +603,7 @@ class AudioPlayer {
} }
Future<Duration> _load(AudioPlayerPlatform platform, AudioSource source, Future<Duration> _load(AudioPlayerPlatform platform, AudioSource source,
{Duration initialPosition, int initialIndex}) async { {_InitialSeekValues initialSeekValues}) async {
try { try {
if (!kIsWeb && source._requiresHeaders) { if (!kIsWeb && source._requiresHeaders) {
if (_proxy == null) { if (_proxy == null) {
@ -610,18 +612,21 @@ class AudioPlayer {
} }
} }
await source._setup(this); await source._setup(this);
source._shuffle(initialIndex: initialIndex ?? 0); source._shuffle(initialIndex: initialSeekValues?.index ?? 0);
_updateShuffleIndices(); _updateShuffleIndices();
platform ??= await _platform; platform ??= await _platform;
_durationFuture = platform _durationFuture = platform
.load(LoadRequest( .load(LoadRequest(
audioSourceMessage: source._toMessage(), audioSourceMessage: source._toMessage(),
initialPosition: initialPosition, initialPosition: initialSeekValues?.position,
initialIndex: initialIndex, initialIndex: initialSeekValues?.index,
)) ))
.then((response) => response.duration); .then((response) => response.duration);
final duration = await _durationFuture; final duration = await _durationFuture;
_durationSubject.add(duration); _durationSubject.add(duration);
// Wait for loading state to pass.
await processingStateStream
.firstWhere((state) => state != ProcessingState.loading);
return duration; return duration;
} on PlatformException catch (e) { } on PlatformException catch (e) {
try { try {
@ -653,9 +658,6 @@ class AudioPlayer {
start: start, start: start,
end: end, end: end,
)); ));
// Wait for loading state to pass.
await processingStateStream
.firstWhere((state) => state != ProcessingState.loading);
return duration; return duration;
} }
@ -917,11 +919,6 @@ class AudioPlayer {
final position = this.position; final position = this.position;
final currentIndex = this.currentIndex; final currentIndex = this.currentIndex;
final audioSource = _audioSource; final audioSource = _audioSource;
final newPlatform = active
? (_nativePlatform =
JustAudioPlatform.instance.init(InitRequest(id: _id)))
: Future.value(_idlePlatform);
_playbackEventSubscription?.cancel();
final durationCompleter = Completer<Duration>(); final durationCompleter = Completer<Duration>();
_platform = Future<AudioPlayerPlatform>(() async { _platform = Future<AudioPlayerPlatform>(() async {
if (oldPlatformFuture != null) { if (oldPlatformFuture != null) {
@ -932,7 +929,11 @@ class AudioPlayer {
} }
// During initialisation, we must only use this platform reference in case // During initialisation, we must only use this platform reference in case
// _platform is updated again during initialisation. // _platform is updated again during initialisation.
final platform = await newPlatform; final platform = active
? await (_nativePlatform =
JustAudioPlatform.instance.init(InitRequest(id: _id)))
: _idlePlatform;
_playbackEventSubscription?.cancel();
_playbackEventSubscription = _playbackEventSubscription =
platform.playbackEventMessageStream.listen((message) { platform.playbackEventMessageStream.listen((message) {
var duration = message.duration; var duration = message.duration;
@ -999,20 +1000,9 @@ class AudioPlayer {
} }
if (audioSource != null) { if (audioSource != null) {
try { try {
Duration initialPosition;
int initialIndex;
if (_initialSeekValues != null) {
initialPosition = _initialSeekValues.position;
initialIndex = _initialSeekValues.index;
} else {
initialPosition = position;
initialIndex = currentIndex;
}
final duration = await _load(platform, _audioSource, final duration = await _load(platform, _audioSource,
initialPosition: initialPosition, initialIndex: initialIndex); initialSeekValues: _initialSeekValues ??
// Wait for loading state to pass. _InitialSeekValues(position: position, index: currentIndex));
await processingStateStream
.firstWhere((state) => state != ProcessingState.loading);
durationCompleter.complete(duration); durationCompleter.complete(duration);
} catch (e, stackTrace) { } catch (e, stackTrace) {
_audioSource = null; _audioSource = null;

File diff suppressed because it is too large Load Diff

View File

@ -15,12 +15,12 @@ class JustAudioPlugin extends JustAudioPlatform {
} }
Future<AudioPlayerPlatform> init(InitRequest request) async { Future<AudioPlayerPlatform> init(InitRequest request) async {
final player = Html5AudioPlayer(id: request.id);
if (players.containsKey(request.id)) { if (players.containsKey(request.id)) {
throw PlatformException( throw PlatformException(
code: "error", code: "error",
message: "Platform player ${request.id} already exists"); message: "Platform player ${request.id} already exists");
} }
final player = Html5AudioPlayer(id: request.id);
players[request.id] = player; players[request.id] = player;
return player; return player;
} }