Broadcast correct position during seek in iOS

This commit is contained in:
Ryan Heise 2020-08-01 04:25:04 +10:00
parent 4695d53398
commit 2596da4a5b
2 changed files with 22 additions and 0 deletions

View File

@ -293,6 +293,7 @@
} else if (drift < -100) { } else if (drift < -100) {
NSLog(@"stall detected: %lld", drift); NSLog(@"stall detected: %lld", drift);
_buffering = YES; _buffering = YES;
[self updatePosition];
[self broadcastPlaybackEvent]; [self broadcastPlaybackEvent];
} }
} }
@ -347,6 +348,7 @@
- (void)setPlaybackBufferingState:(enum PlaybackState)state buffering:(BOOL)buffering { - (void)setPlaybackBufferingState:(enum PlaybackState)state buffering:(BOOL)buffering {
_buffering = buffering; _buffering = buffering;
[self updatePosition];
[self setPlaybackState:state]; [self setPlaybackState:state];
} }
@ -453,6 +455,7 @@
if (skipMode) { if (skipMode) {
_buffering = _player.currentItem.playbackBufferEmpty; // || !_player.currentItem.playbackLikelyToKeepUp; _buffering = _player.currentItem.playbackBufferEmpty; // || !_player.currentItem.playbackLikelyToKeepUp;
[self updatePosition];
} }
} }
@ -648,16 +651,19 @@
if (_playing) { if (_playing) {
if (@available(macOS 10.12, iOS 10.0, *)) { if (@available(macOS 10.12, iOS 10.0, *)) {
_buffering = _player.timeControlStatus == AVPlayerTimeControlStatusWaitingToPlayAtSpecifiedRate; _buffering = _player.timeControlStatus == AVPlayerTimeControlStatusWaitingToPlayAtSpecifiedRate;
[self updatePosition];
} else { } else {
// If this happens when we're playing, check whether buffer is confirmed // If this happens when we're playing, check whether buffer is confirmed
if (_bufferUnconfirmed && !_player.currentItem.playbackBufferFull) { if (_bufferUnconfirmed && !_player.currentItem.playbackBufferFull) {
// Stay in bufering // Stay in bufering
} else { } else {
_buffering = _player.currentItem.playbackBufferEmpty;// || !_player.currentItem.playbackLikelyToKeepUp; _buffering = _player.currentItem.playbackBufferEmpty;// || !_player.currentItem.playbackLikelyToKeepUp;
[self updatePosition];
} }
} }
} else { } else {
_buffering = _player.currentItem.playbackBufferEmpty;// || !_player.currentItem.playbackLikelyToKeepUp; _buffering = _player.currentItem.playbackBufferEmpty;// || !_player.currentItem.playbackLikelyToKeepUp;
[self updatePosition];
} }
// XXX: Maybe if _state == connecting? // XXX: Maybe if _state == connecting?
// Although then make sure connecting is only used for this purpose. // Although then make sure connecting is only used for this purpose.
@ -693,6 +699,7 @@
if (_bufferUnconfirmed && playerItem.playbackBufferFull) { if (_bufferUnconfirmed && playerItem.playbackBufferFull) {
_bufferUnconfirmed = NO; _bufferUnconfirmed = NO;
_buffering = NO; _buffering = NO;
[self updatePosition];
NSLog(@"Buffering confirmed! leaving buffering"); NSLog(@"Buffering confirmed! leaving buffering");
[self broadcastPlaybackEvent]; [self broadcastPlaybackEvent];
} }
@ -700,10 +707,12 @@
} else { } else {
if (playerItem.playbackBufferEmpty) { if (playerItem.playbackBufferEmpty) {
_buffering = YES; _buffering = YES;
[self updatePosition];
NSLog(@"[%d] BUFFERING YES: playbackBufferEmpty = %d, playbackBufferFull = %d", [self indexForItem:playerItem], playerItem.playbackBufferEmpty, playerItem.playbackBufferFull); NSLog(@"[%d] BUFFERING YES: playbackBufferEmpty = %d, playbackBufferFull = %d", [self indexForItem:playerItem], playerItem.playbackBufferEmpty, playerItem.playbackBufferFull);
[self broadcastPlaybackEvent]; [self broadcastPlaybackEvent];
} else if (!playerItem.playbackBufferEmpty || playerItem.playbackBufferFull) { } else if (!playerItem.playbackBufferEmpty || playerItem.playbackBufferFull) {
_buffering = NO; _buffering = NO;
[self updatePosition];
NSLog(@"[%d] BUFFERING NO: playbackBufferEmpty = %d, playbackBufferFull = %d", [self indexForItem:playerItem], playerItem.playbackBufferEmpty, playerItem.playbackBufferFull); NSLog(@"[%d] BUFFERING NO: playbackBufferEmpty = %d, playbackBufferFull = %d", [self indexForItem:playerItem], playerItem.playbackBufferEmpty, playerItem.playbackBufferFull);
[self broadcastPlaybackEvent]; [self broadcastPlaybackEvent];
} }
@ -756,9 +765,11 @@
[_player pause]; [_player pause];
} }
_buffering = YES; _buffering = YES;
[self updatePosition];
[self broadcastPlaybackEvent]; [self broadcastPlaybackEvent];
[source seek:kCMTimeZero completionHandler:^(BOOL finished) { [source seek:kCMTimeZero completionHandler:^(BOOL finished) {
_buffering = NO; _buffering = NO;
[self updatePosition];
[self broadcastPlaybackEvent]; [self broadcastPlaybackEvent];
if (shouldResumePlayback) { if (shouldResumePlayback) {
_player.actionAtItemEnd = originalEndAction; _player.actionAtItemEnd = originalEndAction;
@ -936,6 +947,7 @@
IndexedAudioSource *source = _indexedAudioSources[_index]; IndexedAudioSource *source = _indexedAudioSources[_index];
if (abs((int)(1000 * CMTimeGetSeconds(CMTimeSubtract(source.position, position)))) > 100) { if (abs((int)(1000 * CMTimeGetSeconds(CMTimeSubtract(source.position, position)))) > 100) {
_buffering = YES; _buffering = YES;
[self updatePosition];
[self broadcastPlaybackEvent]; [self broadcastPlaybackEvent];
[source seek:position completionHandler:^(BOOL finished) { [source seek:position completionHandler:^(BOOL finished) {
if (@available(macOS 10.12, iOS 10.0, *)) { if (@available(macOS 10.12, iOS 10.0, *)) {
@ -946,6 +958,7 @@
// Stay in buffering // Stay in buffering
} else if (source.playerItem.status == AVPlayerItemStatusReadyToPlay) { } else if (source.playerItem.status == AVPlayerItemStatusReadyToPlay) {
_buffering = NO; _buffering = NO;
[self updatePosition];
[self broadcastPlaybackEvent]; [self broadcastPlaybackEvent];
} }
} }
@ -954,6 +967,7 @@
// Stay in buffering // Stay in buffering
} else if (source.playerItem.status == AVPlayerItemStatusReadyToPlay) { } else if (source.playerItem.status == AVPlayerItemStatusReadyToPlay) {
_buffering = NO; _buffering = NO;
[self updatePosition];
[self broadcastPlaybackEvent]; [self broadcastPlaybackEvent];
} }
} }
@ -983,6 +997,7 @@
// TODO: Move this into a separate method so it can also // TODO: Move this into a separate method so it can also
// be used in skip. // be used in skip.
_buffering = YES; _buffering = YES;
[self updatePosition];
[self broadcastPlaybackEvent]; [self broadcastPlaybackEvent];
[_indexedAudioSources[_index] seek:position completionHandler:^(BOOL finished) { [_indexedAudioSources[_index] seek:position completionHandler:^(BOOL finished) {
[self updatePosition]; [self updatePosition];
@ -997,6 +1012,7 @@
// !playbackBufferEmpty. Although this always seems to // !playbackBufferEmpty. Although this always seems to
// be full even right after a seek. // be full even right after a seek.
_buffering = _player.currentItem.playbackBufferEmpty; _buffering = _player.currentItem.playbackBufferEmpty;
[self updatePosition];
if (!_buffering) { if (!_buffering) {
[self broadcastPlaybackEvent]; [self broadcastPlaybackEvent];
} }

View File

@ -494,6 +494,12 @@ class AudioPlayer {
/// from any state except for [AudioPlaybackState.none] and /// from any state except for [AudioPlaybackState.none] and
/// [AudioPlaybackState.connecting]. /// [AudioPlaybackState.connecting].
Future<void> seek(final Duration position, {int index}) async { Future<void> seek(final Duration position, {int index}) async {
// Update local state immediately so that queries aren't surprised.
_audioPlaybackEvent = _audioPlaybackEvent.copyWith(
updatePosition: position,
updateTime: Duration(milliseconds: DateTime.now().millisecondsSinceEpoch),
);
_playbackEventSubject.add(_audioPlaybackEvent);
await _invokeMethod('seek', [position?.inMilliseconds, index]); await _invokeMethod('seek', [position?.inMilliseconds, index]);
} }