diff --git a/packages/sane/example/main.dart b/packages/sane/example/main.dart index b6d5de2..6805c99 100644 --- a/packages/sane/example/main.dart +++ b/packages/sane/example/main.dart @@ -5,7 +5,7 @@ import 'dart:typed_data'; import 'package:logging/logging.dart'; import 'package:sane/sane.dart'; -import 'package:sane/src/impl/sane_dev.dart'; +import 'package:sane/src/impl/sane_mock.dart'; import 'package:sane/src/impl/sane_native.dart'; void main(List args) async { @@ -79,4 +79,6 @@ void main(List args) async { ); final rawPixelData = mergeUint8Lists(rawPixelDataList); file.writeAsBytesSync(rawPixelData, mode: FileMode.append); + + await sane.dispose(); } diff --git a/packages/sane/lib/src/extensions.dart b/packages/sane/lib/src/extensions.dart index 0f0d5fb..45dc791 100644 --- a/packages/sane/lib/src/extensions.dart +++ b/packages/sane/lib/src/extensions.dart @@ -1,4 +1,5 @@ import 'package:meta/meta.dart'; +import 'package:logging/logging.dart'; import 'package:sane/src/bindings.g.dart'; import 'package:sane/src/exceptions.dart'; @@ -12,3 +13,16 @@ extension SaneStatusExtension on SANE_Status { } } } + +@internal +extension LoggerExtension on Logger { + void redirect(LogRecord record) { + log( + record.level, + record.message, + record.error, + record.stackTrace, + record.zone, + ); + } +} diff --git a/packages/sane/lib/src/impl/sane_dev.dart b/packages/sane/lib/src/impl/sane_mock.dart similarity index 99% rename from packages/sane/lib/src/impl/sane_dev.dart rename to packages/sane/lib/src/impl/sane_mock.dart index bf5d78f..6e887e1 100644 --- a/packages/sane/lib/src/impl/sane_dev.dart +++ b/packages/sane/lib/src/impl/sane_mock.dart @@ -4,7 +4,7 @@ import 'dart:typed_data'; import 'package:logging/logging.dart'; import 'package:sane/sane.dart'; -final _logger = Logger('sane.dev'); +final _logger = Logger('sane.mock'); class MockSane implements Sane { @override diff --git a/packages/sane/lib/src/impl/sane_native.dart b/packages/sane/lib/src/impl/sane_native.dart index 39955f9..538c69a 100644 --- a/packages/sane/lib/src/impl/sane_native.dart +++ b/packages/sane/lib/src/impl/sane_native.dart @@ -81,17 +81,19 @@ class NativeSane implements Sane { Future dispose({bool force = false}) async { final isolate = _isolate; - if (force) { - isolate?.kill(); - return; - } - if (_disposed) return; _disposed = true; _instance = null; - await isolate?.sendMessage(ExitMessage()); + if (isolate == null) return; + + if (force) { + isolate.killImmediately(); + } else { + await isolate.sendMessage(ExitMessage()); + isolate.kill(); + } _isolate = null; } diff --git a/packages/sane/lib/src/isolate.dart b/packages/sane/lib/src/isolate.dart index 65117a2..ae16836 100644 --- a/packages/sane/lib/src/isolate.dart +++ b/packages/sane/lib/src/isolate.dart @@ -1,11 +1,17 @@ import 'dart:async'; import 'dart:isolate'; +import 'package:logging/logging.dart'; +import 'package:meta/meta.dart'; import 'package:sane/src/exceptions.dart'; +import 'package:sane/src/extensions.dart'; import 'package:sane/src/isolate_messages/exception.dart'; import 'package:sane/src/isolate_messages/interface.dart'; import 'package:sane/src/sane.dart'; +final _logger = Logger('sane.isolate'); + +@internal class SaneIsolate { SaneIsolate._( this._isolate, @@ -36,14 +42,28 @@ class SaneIsolate { onExit: exitReceivePort.sendPort, ); - final sendPort = await receivePort.first as SendPort; + final sendPortCompleter = Completer(); + receivePort.listen((message) { + switch (message) { + case SendPort(): + sendPortCompleter.complete(message); + case LogRecord(): + _logger.redirect(message); + } + }); + + final sendPort = await sendPortCompleter.future; return SaneIsolate._(isolate, sendPort, exitReceivePort); } - void kill() { + void killImmediately() { _isolate.kill(priority: Isolate.immediate); } + void kill() { + _isolate.kill(priority: Isolate.beforeNextEvent); + } + Future sendMessage( IsolateMessage message, ) async { @@ -75,6 +95,9 @@ typedef _EntryPointArgs = (SendPort sendPort, Sane sane); void _entryPoint(_EntryPointArgs args) { final (sendPort, sane) = args; + Logger.root.level = Level.ALL; + Logger.root.onRecord.forEach(sendPort.send); + final receivePort = ReceivePort(); sendPort.send(receivePort.sendPort); @@ -108,8 +131,10 @@ class _IsolateMessageEnvelope { late Map _devices; +@internal SaneDevice getDevice(String name) => _devices[name]!; +@internal void setDevices(Iterable devices) { _devices = { for (final device in devices) device.name: device, diff --git a/packages/sane/lib/src/isolate_messages/get_devices.dart b/packages/sane/lib/src/isolate_messages/get_devices.dart index cb12eda..ed6ef37 100644 --- a/packages/sane/lib/src/isolate_messages/get_devices.dart +++ b/packages/sane/lib/src/isolate_messages/get_devices.dart @@ -1,3 +1,4 @@ +import 'package:sane/src/isolate.dart'; import 'package:sane/src/isolate_messages/interface.dart'; import 'package:sane/src/sane.dart'; @@ -8,14 +9,14 @@ class GetDevicesMessage implements IsolateMessage { @override Future handle(Sane sane) async { - return GetDevicesResponse( - devices: await sane.getDevices(localOnly: localOnly), - ); + final devices = await sane.getDevices(localOnly: localOnly); + setDevices(devices); + return GetDevicesResponse(devices); } } class GetDevicesResponse implements IsolateResponse { - GetDevicesResponse({required this.devices}); + GetDevicesResponse(this.devices); final List devices; } diff --git a/packages/sane/lib/src/sane.dart b/packages/sane/lib/src/sane.dart index 821f883..05d5452 100644 --- a/packages/sane/lib/src/sane.dart +++ b/packages/sane/lib/src/sane.dart @@ -3,7 +3,7 @@ import 'dart:typed_data'; import 'package:meta/meta.dart'; import 'package:sane/sane.dart'; -import 'package:sane/src/impl/sane_dev.dart'; +import 'package:sane/src/impl/sane_mock.dart'; import 'package:sane/src/impl/sane_native.dart'; import 'package:sane/src/impl/sane_sync.dart'; @@ -15,7 +15,7 @@ abstract interface class Sane { /// See also: /// /// - [Sane.sync] - factory Sane() => NativeSane(); + factory Sane([Sane? backingSane]) => NativeSane(backingSane); /// Instantiates a new synchronous SANE instance. factory Sane.sync() => SyncSane(); diff --git a/packages/sane/test/sane_singleton_test.dart b/packages/sane/test/sane_singleton_test.dart index b033bbf..377f34c 100644 --- a/packages/sane/test/sane_singleton_test.dart +++ b/packages/sane/test/sane_singleton_test.dart @@ -1,9 +1,18 @@ +import 'package:logging/logging.dart'; import 'package:sane/sane.dart'; import 'package:test/test.dart'; void main() { late Sane sane; + setUp(() { + Logger.root.level = Level.ALL; + Logger.root.onRecord.listen((record) { + // ignore: avoid_print + print('${record.level.name}: ${record.time}: ${record.message}'); + }); + }); + test('can instantiate', () { sane = Sane(); }); @@ -25,7 +34,7 @@ void main() { }); test('can reinstiate with new instance', () { - final newSane = Sane(); + final newSane = Sane(Sane.mock()); expect(sane, isNot(newSane)); sane = newSane; });