Skip to content

Commit 8ba21f0

Browse files
committed
Add README to Dart bindings
1 parent 5460dc2 commit 8ba21f0

File tree

4 files changed

+301
-58
lines changed

4 files changed

+301
-58
lines changed

rust/bindings/dart/README.md

Lines changed: 184 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,200 @@
1-
<!--
2-
This README describes the package. If you publish this package to pub.dev,
3-
this README's contents appear on the landing page for your package.
1+
Control
2+
[`virtual-display-rs`](https://github.com/MolotovCherry/virtual-display-rs)
3+
using Dart, to create and manage virtual monitors on Windows.
44

5-
For information about how to write a good package README, see the guide for
6-
[writing package pages](https://dart.dev/guides/libraries/writing-package-pages).
5+
`virtual-display-rs` uses windows named pipes to connect to the driver.
76

8-
For general information about developing packages, see the Dart guide for
9-
[creating packages](https://dart.dev/guides/libraries/create-library-packages)
10-
and the Flutter guide for
11-
[developing packages and plugins](https://flutter.dev/developing-packages).
12-
-->
13-
14-
TODO: Put a short description of the package here that helps potential users
15-
know whether this package might be useful for them.
7+
> Note: This package uses [native
8+
> assets](https://github.com/dart-lang/sdk/issues/50565), which are not yet
9+
> stable. To use this package, you must enable it using the
10+
> `--enable-experiment=native-assets` as the first flag on every dart command,
11+
> or, when using flutter, enable it in the flutter config using `flutter config
12+
> --enable-native-assets`.
1613
1714
## Features
1815

19-
TODO: List what your package can do. Maybe include images, gifs, or videos.
16+
- Add/Remove/Change virtual monitors
17+
- Add/Remove/Change monitor resolutions and framerate
18+
- Persist driver state across restarts
19+
- Get continues state updates from the driver, no matter why it changed
2020

2121
## Getting started
2222

23-
TODO: List prerequisites and provide or point to information on how to
24-
start using the package.
23+
1. [Install the driver](https://github.com/MolotovCherry/virtual-display-rs?tab=readme-ov-file#how-to-install)
24+
2. Install Rust using [rustup](https://www.rust-lang.org/learn/get-started)
25+
3. Add dependency to `pubspec.yaml`:
26+
27+
```yaml
28+
dependencies:
29+
vdd:
30+
git:
31+
url: https://github.com/MolotovCherry/virtual-display-rs.git
32+
ref: master
33+
path: rust/bindings/dart
34+
```
2535
2636
## Usage
2737
28-
TODO: Include short and useful examples for package users. Add longer examples
29-
to `/example` folder.
38+
Import the relevant packages:
39+
40+
```dart
41+
import 'package:vdd/vdd.dart' as vdd;
42+
43+
// Imports all errors, that might be thrown by dart_vdd
44+
import 'package:vdd/errors.dart' as vdd;
45+
```
46+
47+
### Initialization
48+
49+
Before using the driver, `vdd` must be initialized:
50+
51+
```dart
52+
await vdd.init();
53+
```
54+
55+
There are two clients with a different level of abstraction.
56+
57+
### `Client`
58+
59+
This client does not manage its own state.
3060

3161
```dart
32-
const like = 'sample';
62+
// Connect to driver using the default named pipe
63+
final client = await vdd.Client.connect();
64+
65+
// Listen to all state changes
66+
client.receiveEvents().listen((monitors) {
67+
print("Driver state changed: $monitors");
68+
});
69+
70+
final monitors = [
71+
vdd.Monitor(
72+
id: 0,
73+
enabled: true,
74+
modes: [
75+
vdd.Mode(
76+
width: 1920,
77+
height: 1080,
78+
refreshRates: Uint32List.fromList([60, 120]),
79+
),
80+
],
81+
),
82+
];
83+
84+
// Override driver state with new monitor
85+
await client.notify(monitors: monitors);
86+
87+
// Make this state persistent across restarts
88+
await vdd.Client.persist(monitors: monitors);
89+
```
90+
91+
### `DriverClient`
92+
93+
This client manages its own state, separate from the driver. This state might
94+
become stale. To refresh it, call `DriverClient.refreshState`. To apply state
95+
changes to the driver, call `DriverClient.notify`.
96+
97+
```dart
98+
// Connect to the driver, using the default pipe name
99+
final client = await vdd.DriverClient.connect();
100+
101+
// Listen to all state changes
102+
client.receiveEvents().listen((monitors) async {
103+
print("Driver state changed: $monitors");
104+
105+
// Refresh local state when driver state changes
106+
await client.refreshState();
107+
});
108+
109+
print("Current driver state: ${client.state}");
110+
111+
// Get a free id for a new monitor
112+
final monitorId = client.newId()!;
113+
114+
// Add a new monitor
115+
client.add(
116+
monitor: vdd.Monitor(
117+
id: monitorId,
118+
enabled: true,
119+
modes: [
120+
vdd.Mode(
121+
width: 1920,
122+
height: 1080,
123+
refreshRates: Uint32List.fromList([60, 120]),
124+
),
125+
],
126+
),
127+
);
128+
129+
// Apply changes to the driver
130+
await client.notify();
131+
132+
// Make changes persistent across restarts
133+
await client.persist();
134+
```
135+
136+
## Testing
137+
138+
`vdd` provides a mock server, simulating the driver on the other end of the
139+
named pipe.
140+
141+
Additionally, import `package:vdd/test.dart` to get access to the mock server.
142+
143+
```dart
144+
import 'package:vdd/vdd.dart' as vdd;
145+
import 'package:vdd/test.dart' as vdd;
146+
```
147+
148+
```dart
149+
setUpAll(() async {
150+
await vdd.init();
151+
});
152+
153+
test('test', () async {
154+
// Pass in a unique pipe name
155+
final server = await vdd.MockServer.create(pipeName: "my_pipe_name");
156+
final client = await vdd.Client.connect(server.pipeName);
157+
158+
// Use the client
159+
await client.notify(...);
160+
161+
// Pump the server, to handle exactly one request
162+
await server.pump();
163+
164+
expect(server.state, ...);
165+
166+
await server.setState(...);
167+
168+
expect(client.requestState(), ...);
169+
});
170+
```
171+
172+
For more examples, see the
173+
[tests](https://github.com/MolotovCherry/virtual-display-rs/tree/master/rust/bindings/dart/test/vdd_test.dart)
174+
in `test/`.
175+
176+
## Maintaining
177+
178+
To regenerate bindings, run:
179+
180+
```bash
181+
cargo make generate
182+
```
183+
184+
or
185+
186+
```bash
187+
cargo make generate-watch
188+
```
189+
190+
To run unit tests, run:
191+
192+
```bash
193+
cargo make test
33194
```
34195

35-
## Additional information
196+
To run examples, run:
36197

37-
TODO: Tell users more about the package: where to find more information, how to
38-
contribute to the package, how to file issues, what response they can expect
39-
from the package authors, and more.
198+
```bash
199+
dart --enable-experiment=native-assets run example/<example>.dart
200+
```
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import 'dart:typed_data';
2+
3+
import 'package:vdd/errors.dart' as vdd;
4+
import 'package:vdd/vdd.dart' as vdd;
5+
6+
void main(List<String> args) async {
7+
await vdd.init();
8+
9+
// Connect to driver using the default named pipe
10+
final client = await vdd.Client.connect();
11+
12+
try {
13+
print("Current state: ${await client.requestState()}");
14+
} on vdd.RequestError catch (e) {
15+
print("Did you forget to install the driver?\n$e");
16+
return;
17+
}
18+
19+
// Listen to all state changes
20+
client.receiveEvents().listen((monitors) {
21+
print("Driver state changed: $monitors");
22+
});
23+
24+
final monitors = [
25+
vdd.Monitor(
26+
id: 0,
27+
enabled: true,
28+
modes: [
29+
vdd.Mode(
30+
width: 1920,
31+
height: 1080,
32+
refreshRates: Uint32List.fromList([60, 120]),
33+
),
34+
],
35+
),
36+
];
37+
38+
// Override driver state with new monitor
39+
await client.notify(monitors: monitors);
40+
41+
// Make this state persistent across restarts
42+
await vdd.Client.persist(monitors: monitors);
43+
44+
await Future.delayed(Duration(seconds: 5));
45+
46+
// Remove all monitors
47+
await client.removeAll();
48+
49+
await vdd.Client.persist(monitors: []);
50+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import 'dart:typed_data';
2+
3+
import 'package:vdd/errors.dart' as vdd;
4+
import 'package:vdd/vdd.dart' as vdd;
5+
6+
void main(List<String> args) async {
7+
await vdd.init();
8+
9+
try {
10+
// Connect to the driver, using the default pipe name
11+
final client = await vdd.DriverClient.connect();
12+
13+
// Listen to all state changes
14+
client.receiveEvents().listen((monitors) async {
15+
print("Driver state changed: $monitors");
16+
17+
// Refresh local state when driver state changes
18+
await client.refreshState();
19+
});
20+
21+
print("Current driver state: ${client.state}");
22+
23+
// Get a free id for a new monitor
24+
final monitorId = client.newId()!;
25+
26+
// Add a new monitor
27+
client.add(
28+
monitor: vdd.Monitor(
29+
id: monitorId,
30+
enabled: true,
31+
modes: [
32+
vdd.Mode(
33+
width: 1920,
34+
height: 1080,
35+
refreshRates: Uint32List.fromList([60, 120]),
36+
),
37+
],
38+
),
39+
);
40+
41+
client.addMode(
42+
id: monitorId,
43+
mode: vdd.Mode(
44+
width: 2560,
45+
height: 1440,
46+
refreshRates: Uint32List.fromList([60, 120]),
47+
),
48+
);
49+
50+
// Apply changes to the driver
51+
await client.notify();
52+
53+
// Make changes persistent across restarts
54+
await client.persist();
55+
56+
await Future.delayed(Duration(seconds: 5));
57+
58+
// Remove all monitors
59+
client.removeAll();
60+
61+
await client.notify();
62+
63+
await client.persist();
64+
} on vdd.InitError catch (e) {
65+
print("Did you forget to install the driver?\n$e");
66+
}
67+
}

rust/bindings/dart/example/vdd_example.dart

Lines changed: 0 additions & 35 deletions
This file was deleted.

0 commit comments

Comments
 (0)