Update state before method channel calls complete.

This commit is contained in:
Ryan Heise 2020-04-18 14:28:06 +10:00
parent b10583e8d6
commit 5e9a707e08
3 changed files with 88 additions and 23 deletions

View File

@ -115,9 +115,9 @@ public class AudioPlayer implements MethodCallHandler, Player.EventListener {
if (prepareResult != null) {
duration = player.getDuration();
justConnected = true;
transition(PlaybackState.stopped);
prepareResult.success(duration);
prepareResult = null;
transition(PlaybackState.stopped);
}
if (seekProcessed) {
completeSeek();

View File

@ -92,7 +92,7 @@ packages:
path: ".."
relative: true
source: path
version: "0.1.4"
version: "0.1.5"
matcher:
dependency: transitive
description:

View File

@ -233,6 +233,15 @@ class AudioPlayer {
/// * [AudioPlaybackState.connecting]
/// * [AudioPlaybackState.none]
Future<void> play() async {
switch (playbackState) {
case AudioPlaybackState.playing:
case AudioPlaybackState.stopped:
case AudioPlaybackState.completed:
case AudioPlaybackState.paused:
// Update local state immediately so that queries aren't surprised.
_audioPlaybackEvent = _audioPlaybackEvent.copyWith(
state: AudioPlaybackState.playing,
);
StreamSubscription subscription;
Completer completer = Completer();
bool startedPlaying = false;
@ -252,12 +261,32 @@ class AudioPlayer {
});
await _invokeMethod('play');
await completer.future;
break;
default:
throw Exception(
"Cannot call play from connecting/none states ($playbackState)");
}
}
/// Pauses the currently playing media. It is legal to invoke this method
/// only from the [AudioPlaybackState.playing] state.
Future<void> pause() async {
switch (playbackState) {
case AudioPlaybackState.paused:
break;
case AudioPlaybackState.playing:
// Update local state immediately so that queries aren't surprised.
_audioPlaybackEvent = _audioPlaybackEvent.copyWith(
state: AudioPlaybackState.paused,
);
// TODO: For pause, perhaps modify platform side to ensure new state
// is broadcast before this method returns.
await _invokeMethod('pause');
break;
default:
throw Exception(
"Can call pause only from playing and buffering states ($playbackState)");
}
}
/// Stops the currently playing media such that the next [play] invocation
@ -268,7 +297,24 @@ class AudioPlayer {
/// * [AudioPlaybackState.paused]
/// * [AudioPlaybackState.completed]
Future<void> stop() async {
switch (playbackState) {
case AudioPlaybackState.stopped:
break;
case AudioPlaybackState.connecting:
case AudioPlaybackState.completed:
case AudioPlaybackState.playing:
case AudioPlaybackState.paused:
// Update local state immediately so that queries aren't surprised.
// NOTE: Android implementation already handles this.
// TODO: Do the same for iOS so the line below becomes unnecessary.
_audioPlaybackEvent = _audioPlaybackEvent.copyWith(
state: AudioPlaybackState.paused,
);
await _invokeMethod('stop');
break;
default:
throw Exception("Cannot call stop from none state");
}
}
/// Sets the volume of this player, where 1.0 is normal volume.
@ -354,6 +400,25 @@ class AudioPlaybackEvent {
@required this.duration,
});
AudioPlaybackEvent copyWith({
AudioPlaybackState state,
bool buffering,
Duration updateTime,
Duration updatePosition,
Duration bufferedPosition,
double speed,
Duration duration,
}) =>
AudioPlaybackEvent(
state: state ?? this.state,
buffering: buffering ?? this.buffering,
updateTime: updateTime ?? this.updateTime,
updatePosition: updatePosition ?? this.updatePosition,
bufferedPosition: bufferedPosition ?? this.bufferedPosition,
speed: speed ?? this.speed,
duration: duration ?? this.duration,
);
/// The current position of the player.
Duration get position {
if (state == AudioPlaybackState.playing && !buffering) {