seek method

Future<void> seek(
  1. int targetUs
)

Seeks to targetUs.

The audio thread is suspended across the whole operation. That is not politeness: the worker clears the ring as part of seeking, and clearing it under a live consumer would let one buffer of already-committed samples be overwritten mid-read — a click at exactly the moment a seek is supposed to be clean.

Implementation

Future<void> seek(int targetUs) async {
  if (_closed) return;
  final before = await _seekGeneration();
  await _sink.suspend();
  try {
    await _worker.request<Object?>(<Object?>['seek', targetUs]);
    // Wait for the pump to actually reach the seek: it may have been mid
    // decode, and resuming before it has cleared would play the old
    // position's tail.
    for (var i = 0; i < 100; i++) {
      if (await _seekGeneration() != before) break;
      await Future<void>.delayed(const Duration(milliseconds: 10));
    }
    // Position now advances from the seek target, against the ring's
    // monotonic cursor.
    _baselinePtsUs = targetUs;
    _baselineFrames = _sink.ring.framesConsumed;
  } on Object {
    // A failed seek leaves the stream where it was; the caller sees the
    // position not move rather than an exception out of a transport control.
  } finally {
    // Back to whatever the caller had, NOT unconditionally running: seeking
    // a paused player must leave it paused, or a scrub starts playback.
    if (!_paused) await _sink.resume();
  }
}