disconnect method

Future<void> disconnect()

Implementation

Future<void> disconnect() async {
  // Create completer to wait for isolate to confirm stop
  _isolateStoppedCompleter = Completer<void>();

  // Signal the isolate to stop - this allows it to exit its read loop
  // cleanly before we close the port
  _stopPort?.send(null);
  _stopPort = null;

  // Wait for the isolate to confirm it has stopped (it sends null when done)
  // Use a timeout to avoid hanging if something goes wrong
  if (_isolate != null) {
    try {
      await _isolateStoppedCompleter!.future.timeout(
        const Duration(milliseconds: 100),
        onTimeout: () {},
      );
    } catch (_) {
      // Ignore errors - we'll kill the isolate anyway
    }
  }
  _isolateStoppedCompleter = null;

  // Close receive ports
  receivePort?.close();
  receivePort = null;
  errorPort?.close();
  errorPort = null;

  // Kill the isolate (should already be stopped, but just in case)
  _isolate?.kill(priority: Isolate.immediate);
  _isolate = null;

  // Now it's safe to close the ALSA ports since the isolate has stopped
  var status = 0;
  if (inPort != null) {
    if ((status = alsa.snd_rawmidi_drain(inPort!.value)) < 0) {
      print(
        'error: cannot drain in port $this ${stringFromNative(alsa.snd_strerror(status))}',
      );
    }
    if ((status = alsa.snd_rawmidi_close(inPort!.value)) < 0) {
      print(
        'error: cannot close in port $this ${stringFromNative(alsa.snd_strerror(status))}',
      );
    }
    inPort = null;
  }

  _connectedDevices.remove(hardwareId(cardId, deviceId));
  _disconnectStreamCtrl.add(this);

  // Close output port last
  if (outPort != null) {
    if ((status = alsa.snd_rawmidi_drain(outPort!.value)) < 0) {
      print(
        'error: cannot drain out port $this ${stringFromNative(alsa.snd_strerror(status))}',
      );
    }
    if ((status = alsa.snd_rawmidi_close(outPort!.value)) < 0) {
      print(
        'error: cannot close out port $this ${stringFromNative(alsa.snd_strerror(status))}',
      );
    }
    outPort = null;
  }

  connected = false;
}