writeBytes method

  1. @override
Future writeBytes(
  1. List<int> data, {
  2. int? vendorId,
  3. int? productId,
})
override

Writes data as one RAW spooler job (Windows) or bulk transfer (Android). Uses the connection opened by connect; if none is open, opens one for this write and closes it again afterwards.

Implementation

@override
Future writeBytes(List<int> data, {int? vendorId, int? productId}) async {
  if (Platform.isWindows) {
    final ownHandle = _hPrinter == null;
    PRINTER_HANDLE h;
    try {
      h = _hPrinter ?? _openWindowsPrinter();
    } catch (e) {
      return Future.error(e.toString());
    }
    final pDocName = 'My Document'.toNativeUtf16();
    final pDataType = 'RAW'.toNativeUtf16();
    final dwBytesWritten = calloc<DWORD>();
    final docInfo = calloc<DOC_INFO_1>()
      ..ref.pDocName = PWSTR(pDocName)
      ..ref.pOutputFile = PWSTR(nullptr.cast<Utf16>())
      ..ref.pDatatype = PWSTR(pDataType);
    var docStarted = false;
    var pageStarted = false;
    try {
      if (StartDocPrinter(h, 1, docInfo) == 0) {
        throw Exception('StartDocPrinter failed');
      }
      docStarted = true;
      if (!StartPagePrinter(h)) throw Exception('StartPagePrinter failed');
      pageStarted = true;

      // Send in chunks: writing all at once makes some drivers paginate.
      const int chunkSize = 4096;
      int totalWritten = 0;
      for (final chunk in data.chunkBy(chunkSize)) {
        final lpData = chunk.toUint8();
        try {
          final ok = WritePrinter(h, lpData, chunk.length, dwBytesWritten);
          if (!ok) {
            throw Exception('WritePrinter failed after $totalWritten bytes');
          }
          totalWritten += dwBytesWritten.value;
        } finally {
          calloc.free(lpData);
        }
      }

      pageStarted = false;
      if (!EndPagePrinter(h)) throw Exception('EndPagePrinter failed');
      docStarted = false;
      if (!EndDocPrinter(h)) throw Exception('EndDocPrinter failed');
    } catch (e) {
      return Future.error(e.toString());
    } finally {
      if (pageStarted) EndPagePrinter(h);
      if (docStarted) EndDocPrinter(h);
      if (ownHandle) {
        try {
          ClosePrinter(h);
        } catch (_) {}
      }
      calloc.free(docInfo);
      calloc.free(dwBytesWritten);
      calloc.free(pDocName);
      calloc.free(pDataType);
    }
  } else if (Platform.isAndroid) {
    final ownConnection = !_androidConnected;
    try {
      await connect();
      // maxChunk limit on android
      for (final chunk in data.chunkBy(16384)) {
        final ok = await usbPrinter.write(Uint8List.fromList(chunk));
        if (ok == false) throw Exception('USB write failed');
      }
    } catch (e) {
      return Future.error(e.toString());
    } finally {
      if (ownConnection) await disconnect();
    }
  }
}