connect method

Future<bool> connect()

Implementation

Future<bool> connect() async {
  outPort = calloc<Pointer<a.snd_rawmidi_>>();
  inPort = calloc<Pointer<a.snd_rawmidi_>>();

  Pointer<Char> name = '${hardwareId(cardId, deviceId)},0'
      .toNativeUtf8()
      .cast<Char>();
  var status = 0;
  if ((status = alsa.snd_rawmidi_open(
        inPort!,
        outPort!,
        name,
        a.SND_RAWMIDI_NONBLOCK,
      )) <
      0) {
    print(
      'error: cannot open card number $cardId ${stringFromNative(alsa.snd_strerror(status))}',
    );
    return false;
  }

  connected = true;

  /// Register this device as connected globally
  _connectedDevices[hardwareId(cardId, deviceId)] = this;

  errorPort = ReceivePort();
  receivePort = ReceivePort();

  // Create a port to receive the stop port from the isolate
  final readyPort = ReceivePort();
  final readyCompleter = Completer<SendPort>();
  readyPort.listen((message) {
    if (message is SendPort) {
      readyCompleter.complete(message);
      readyPort.close();
    }
  });

  _isolate = await Isolate.spawn(
    _rxIsolate,
    _RxIsolateArgs(receivePort!.sendPort, inPort!.value.address, readyPort.sendPort),
    onError: errorPort!.sendPort,
  );

  // Wait for the isolate to send us its stop port
  _stopPort = await readyCompleter.future;

  errorPort?.listen((message) {
    print('isolate error message $message');
    disconnect();
  });

  receivePort?.listen((data) {
    if (data == null) {
      // Isolate signaled it has stopped
      _isolateStoppedCompleter?.complete();
      return;
    }
    var packet = MidiMessage(
      data,
      DateTime.now().millisecondsSinceEpoch,
      this,
    );
    _rxStreamCtrl.add(packet);
  });

  return true;
}