78 lines
2.0 KiB
Dart
78 lines
2.0 KiB
Dart
|
|
|
||
|
|
|
||
|
|
class StallDetector {
|
||
|
|
StallDetector({this.threshold = const Duration(seconds: 15)})
|
||
|
|
: assert(threshold > Duration.zero);
|
||
|
|
|
||
|
|
|
||
|
|
final Duration threshold;
|
||
|
|
|
||
|
|
Duration? _lastPos;
|
||
|
|
Duration? _lastBuffer;
|
||
|
|
int? _lastBytes;
|
||
|
|
Duration _lastAdvanceAt = Duration.zero;
|
||
|
|
bool _fired = false;
|
||
|
|
|
||
|
|
|
||
|
|
bool update({
|
||
|
|
required Duration position,
|
||
|
|
required Duration bufferedPosition,
|
||
|
|
required int? bytesDownloaded,
|
||
|
|
required bool isActivelyPlaying,
|
||
|
|
required Duration now,
|
||
|
|
}) {
|
||
|
|
if (!isActivelyPlaying) {
|
||
|
|
_lastPos = position;
|
||
|
|
_lastBuffer = bufferedPosition;
|
||
|
|
_lastBytes = bytesDownloaded;
|
||
|
|
_lastAdvanceAt = now;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
if (_lastPos == null) {
|
||
|
|
_lastPos = position;
|
||
|
|
_lastBuffer = bufferedPosition;
|
||
|
|
_lastBytes = bytesDownloaded;
|
||
|
|
_lastAdvanceAt = now;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
final positionAdvanced = position != _lastPos;
|
||
|
|
final bytesBecameAvailable = bytesDownloaded != null && _lastBytes == null;
|
||
|
|
final hasComparableByteSamples =
|
||
|
|
bytesDownloaded != null && _lastBytes != null;
|
||
|
|
final bytesAdvanced =
|
||
|
|
hasComparableByteSamples && bytesDownloaded != _lastBytes;
|
||
|
|
final bufferAdvanced = bufferedPosition != _lastBuffer;
|
||
|
|
final hasBufferedMedia =
|
||
|
|
bufferedPosition - position > const Duration(seconds: 2);
|
||
|
|
final transportAdvanced = bytesBecameAvailable ||
|
||
|
|
(hasComparableByteSamples
|
||
|
|
? bytesAdvanced
|
||
|
|
: bufferAdvanced || hasBufferedMedia);
|
||
|
|
final progressed = positionAdvanced || transportAdvanced;
|
||
|
|
|
||
|
|
_lastPos = position;
|
||
|
|
_lastBuffer = bufferedPosition;
|
||
|
|
_lastBytes = bytesDownloaded;
|
||
|
|
if (progressed) {
|
||
|
|
_lastAdvanceAt = now;
|
||
|
|
_fired = false;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
if (_fired) return false;
|
||
|
|
if (now - _lastAdvanceAt >= threshold) {
|
||
|
|
_fired = true;
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
void reset() {
|
||
|
|
_lastPos = null;
|
||
|
|
_lastBuffer = null;
|
||
|
|
_lastBytes = null;
|
||
|
|
_lastAdvanceAt = Duration.zero;
|
||
|
|
_fired = false;
|
||
|
|
}
|
||
|
|
}
|