stopCapture method

  1. @override
Future<void> stopCapture()
override

Stop loopback capture.

Implementation

@override
Future<void> stopCapture() async {
  // Don't throw if context is destroyed - just clean up Dart resources
  if (_isDestroyed || _contextHandle == null) {
    await _cleanupCallback();
    return;
  }

  // Don't throw if already stopped - this is idempotent
  if (_callbackHandle == null) {
    return; // Already stopped
  }

  final res = bindings.MiniAV_Loopback_StopCapture(_contextHandle!);

  // A non-success code here means the native WASAPI capture THREAD did not
  // join (MINIAV_ERROR_TIMEOUT after a 5 s wait) — it is still running and
  // still holds this callable's function pointer. The C side deliberately
  // leaks its context on that path for exactly that reason; closing the
  // callable anyway turns the leak into a use-after-free that aborts the
  // VM ("Callback invoked after it has been deleted"). Leak the callable
  // to match.
  if (res == bindings.MiniAVResultCode.MINIAV_SUCCESS ||
      res == bindings.MiniAVResultCode.MINIAV_ERROR_NOT_RUNNING) {
    await _cleanupCallback();
  } else {
    _callbackHandle = null; // dropped, deliberately not closed
    print(
      'Warning: MiniAV_Loopback_StopCapture failed: ${res.name} — the '
      'capture thread may still be running, so its callback is leaked '
      'rather than closed.',
    );
  }
}