From 8ba21f03d1bd4a646be4156d065a410b8d6ad764 Mon Sep 17 00:00:00 2001 From: Dampfwalze <46897578+Dampfwalze@users.noreply.github.com> Date: Thu, 15 Aug 2024 12:45:28 +0200 Subject: [PATCH] Add README to Dart bindings --- rust/bindings/dart/README.md | 207 ++++++++++++++++-- .../bindings/dart/example/client_example.dart | 50 +++++ .../dart/example/driver_client_example.dart | 67 ++++++ rust/bindings/dart/example/vdd_example.dart | 35 --- 4 files changed, 301 insertions(+), 58 deletions(-) create mode 100644 rust/bindings/dart/example/client_example.dart create mode 100644 rust/bindings/dart/example/driver_client_example.dart delete mode 100644 rust/bindings/dart/example/vdd_example.dart diff --git a/rust/bindings/dart/README.md b/rust/bindings/dart/README.md index 02fe8eca..26ff610d 100644 --- a/rust/bindings/dart/README.md +++ b/rust/bindings/dart/README.md @@ -1,39 +1,200 @@ - - -TODO: Put a short description of the package here that helps potential users -know whether this package might be useful for them. +> Note: This package uses [native +> assets](https://github.com/dart-lang/sdk/issues/50565), which are not yet +> stable. To use this package, you must enable it using the +> `--enable-experiment=native-assets` as the first flag on every dart command, +> or, when using flutter, enable it in the flutter config using `flutter config +> --enable-native-assets`. ## Features -TODO: List what your package can do. Maybe include images, gifs, or videos. +- Add/Remove/Change virtual monitors +- Add/Remove/Change monitor resolutions and framerate +- Persist driver state across restarts +- Get continues state updates from the driver, no matter why it changed ## Getting started -TODO: List prerequisites and provide or point to information on how to -start using the package. +1. [Install the driver](https://github.com/MolotovCherry/virtual-display-rs?tab=readme-ov-file#how-to-install) +2. Install Rust using [rustup](https://www.rust-lang.org/learn/get-started) +3. Add dependency to `pubspec.yaml`: + +```yaml +dependencies: + vdd: + git: + url: https://github.com/MolotovCherry/virtual-display-rs.git + ref: master + path: rust/bindings/dart +``` ## Usage -TODO: Include short and useful examples for package users. Add longer examples -to `/example` folder. +Import the relevant packages: + +```dart +import 'package:vdd/vdd.dart' as vdd; + +// Imports all errors, that might be thrown by dart_vdd +import 'package:vdd/errors.dart' as vdd; +``` + +### Initialization + +Before using the driver, `vdd` must be initialized: + +```dart +await vdd.init(); +``` + +There are two clients with a different level of abstraction. + +### `Client` + +This client does not manage its own state. ```dart -const like = 'sample'; +// Connect to driver using the default named pipe +final client = await vdd.Client.connect(); + +// Listen to all state changes +client.receiveEvents().listen((monitors) { + print("Driver state changed: $monitors"); +}); + +final monitors = [ + vdd.Monitor( + id: 0, + enabled: true, + modes: [ + vdd.Mode( + width: 1920, + height: 1080, + refreshRates: Uint32List.fromList([60, 120]), + ), + ], + ), +]; + +// Override driver state with new monitor +await client.notify(monitors: monitors); + +// Make this state persistent across restarts +await vdd.Client.persist(monitors: monitors); +``` + +### `DriverClient` + +This client manages its own state, separate from the driver. This state might +become stale. To refresh it, call `DriverClient.refreshState`. To apply state +changes to the driver, call `DriverClient.notify`. + +```dart +// Connect to the driver, using the default pipe name +final client = await vdd.DriverClient.connect(); + +// Listen to all state changes +client.receiveEvents().listen((monitors) async { + print("Driver state changed: $monitors"); + + // Refresh local state when driver state changes + await client.refreshState(); +}); + +print("Current driver state: ${client.state}"); + +// Get a free id for a new monitor +final monitorId = client.newId()!; + +// Add a new monitor +client.add( + monitor: vdd.Monitor( + id: monitorId, + enabled: true, + modes: [ + vdd.Mode( + width: 1920, + height: 1080, + refreshRates: Uint32List.fromList([60, 120]), + ), + ], + ), +); + +// Apply changes to the driver +await client.notify(); + +// Make changes persistent across restarts +await client.persist(); +``` + +## Testing + +`vdd` provides a mock server, simulating the driver on the other end of the +named pipe. + +Additionally, import `package:vdd/test.dart` to get access to the mock server. + +```dart +import 'package:vdd/vdd.dart' as vdd; +import 'package:vdd/test.dart' as vdd; +``` + +```dart +setUpAll(() async { + await vdd.init(); +}); + +test('test', () async { + // Pass in a unique pipe name + final server = await vdd.MockServer.create(pipeName: "my_pipe_name"); + final client = await vdd.Client.connect(server.pipeName); + + // Use the client + await client.notify(...); + + // Pump the server, to handle exactly one request + await server.pump(); + + expect(server.state, ...); + + await server.setState(...); + + expect(client.requestState(), ...); +}); +``` + +For more examples, see the +[tests](https://github.com/MolotovCherry/virtual-display-rs/tree/master/rust/bindings/dart/test/vdd_test.dart) +in `test/`. + +## Maintaining + +To regenerate bindings, run: + +```bash +cargo make generate +``` + +or + +```bash +cargo make generate-watch +``` + +To run unit tests, run: + +```bash +cargo make test ``` -## Additional information +To run examples, run: -TODO: Tell users more about the package: where to find more information, how to -contribute to the package, how to file issues, what response they can expect -from the package authors, and more. +```bash +dart --enable-experiment=native-assets run example/.dart +``` \ No newline at end of file diff --git a/rust/bindings/dart/example/client_example.dart b/rust/bindings/dart/example/client_example.dart new file mode 100644 index 00000000..5d790c0e --- /dev/null +++ b/rust/bindings/dart/example/client_example.dart @@ -0,0 +1,50 @@ +import 'dart:typed_data'; + +import 'package:vdd/errors.dart' as vdd; +import 'package:vdd/vdd.dart' as vdd; + +void main(List args) async { + await vdd.init(); + + // Connect to driver using the default named pipe + final client = await vdd.Client.connect(); + + try { + print("Current state: ${await client.requestState()}"); + } on vdd.RequestError catch (e) { + print("Did you forget to install the driver?\n$e"); + return; + } + + // Listen to all state changes + client.receiveEvents().listen((monitors) { + print("Driver state changed: $monitors"); + }); + + final monitors = [ + vdd.Monitor( + id: 0, + enabled: true, + modes: [ + vdd.Mode( + width: 1920, + height: 1080, + refreshRates: Uint32List.fromList([60, 120]), + ), + ], + ), + ]; + + // Override driver state with new monitor + await client.notify(monitors: monitors); + + // Make this state persistent across restarts + await vdd.Client.persist(monitors: monitors); + + await Future.delayed(Duration(seconds: 5)); + + // Remove all monitors + await client.removeAll(); + + await vdd.Client.persist(monitors: []); +} diff --git a/rust/bindings/dart/example/driver_client_example.dart b/rust/bindings/dart/example/driver_client_example.dart new file mode 100644 index 00000000..6d23da68 --- /dev/null +++ b/rust/bindings/dart/example/driver_client_example.dart @@ -0,0 +1,67 @@ +import 'dart:typed_data'; + +import 'package:vdd/errors.dart' as vdd; +import 'package:vdd/vdd.dart' as vdd; + +void main(List args) async { + await vdd.init(); + + try { + // Connect to the driver, using the default pipe name + final client = await vdd.DriverClient.connect(); + + // Listen to all state changes + client.receiveEvents().listen((monitors) async { + print("Driver state changed: $monitors"); + + // Refresh local state when driver state changes + await client.refreshState(); + }); + + print("Current driver state: ${client.state}"); + + // Get a free id for a new monitor + final monitorId = client.newId()!; + + // Add a new monitor + client.add( + monitor: vdd.Monitor( + id: monitorId, + enabled: true, + modes: [ + vdd.Mode( + width: 1920, + height: 1080, + refreshRates: Uint32List.fromList([60, 120]), + ), + ], + ), + ); + + client.addMode( + id: monitorId, + mode: vdd.Mode( + width: 2560, + height: 1440, + refreshRates: Uint32List.fromList([60, 120]), + ), + ); + + // Apply changes to the driver + await client.notify(); + + // Make changes persistent across restarts + await client.persist(); + + await Future.delayed(Duration(seconds: 5)); + + // Remove all monitors + client.removeAll(); + + await client.notify(); + + await client.persist(); + } on vdd.InitError catch (e) { + print("Did you forget to install the driver?\n$e"); + } +} diff --git a/rust/bindings/dart/example/vdd_example.dart b/rust/bindings/dart/example/vdd_example.dart deleted file mode 100644 index efc07bab..00000000 --- a/rust/bindings/dart/example/vdd_example.dart +++ /dev/null @@ -1,35 +0,0 @@ -import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; -import 'package:vdd/errors.dart' as vdd; -import 'package:vdd/vdd.dart' as vdd; - -void main() async { - await vdd.init(); - - try { - final client = await vdd.Client.connect(); - - client.receiveEvents().listen((monitors) { - print('Driver changed state: $monitors'); - }); - - await client.notify(monitors: [ - vdd.Monitor( - id: 0, - enabled: true, - modes: [ - vdd.Mode( - width: 1920, - height: 1080, - refreshRates: Uint32List.fromList([60]), - ), - ], - ), - ]); - - await Future.delayed(Duration(seconds: 5)); - - await client.removeAll(); - } on vdd.ConnectionError catch (e) { - print('Error: $e'); - } -}