Evan's Blog
EvanZhu0721 / 公开仓库

SBMS

镜像已同步

SBMS complete the calculation rules for the default logical desktop topology relationship and the physical dimensions of the displays in the Windows multi-screen collaboration system.

上游 GitHub
READ-ONLY MIRROR

README、源码与 Release 已保存到本站;源码视图固定到 commit a37d6c4b。

main/ root / docs
a37d6c4b· 固定源码快照
docs/mapping-plan.md4.9 KB
预览
1# Mapping plan interface
2
3The Rust core supports one process-level mapping plan containing up to sixteen
4groups. A group ID is a stable zero-based IDD connector index (`0..=15`); list
5order is not identity.
6
7```rust
8MappingPlan::new(groups)?;
9MappingSession::start_plan(plan)?;
10MappingSession::start_plan_with_reporter(plan, reporter)?;
11session.groups();
12session.stop()?;
13```
14
15`MappingRoute::Mirror { target }` creates a virtual display, migrates windows
16from the physical target, and starts the GPU mirror and input endpoint.
17`MappingRoute::StreamOnly` only creates and mode-confirms the virtual display.
18It does not create a renderer, migrate windows, or capture input. This is the
19route intended for Sunshine or another external capturer.
20
21Startup rejects an empty plan, more than sixteen groups, duplicate/out-of-range
22group IDs, duplicate physical targets, invalid modes, missing targets, cloned
23GDI targets, and attempts to use an SBMS virtual display as a physical target.
24The plan is atomic: a failure rolls back all groups and restores physical
25topology once. Runtime insertion, deletion, or mutation of individual groups is
26not part of this interface; stop the plan and start a replacement plan.
27
28Each `MappingGroupInfo` exposes:
29
30- stable group/connector ID;
31- requested rational mode;
32- route and physical target, if any;
33- current `\\.\DISPLAYn` name;
34- DisplayConfig monitor path;
35- Sunshine-compatible `{GUID}`, when it can be resolved.
36
37`\\.\DISPLAYn` is temporary and must not be persisted. Use the group ID for
38SBMS configuration and the brace GUID for Sunshine's `output_name`.
39
40Each group may also specify `rotation` as `deg0`, `deg90`, `deg180`, or
41`deg270`; omitted values remain `deg0`. `mode.width` and `mode.height` are the
42final native desktop dimensions published by the IDD. SBMS does not swap a
43portrait mode back to landscape: `1800x2880` remains a native `1800x2880`
44display so applications can detect the portrait surface directly.
45
46The rotation value remains the user's orientation and sizing input. Once those
47inputs have produced the final native dimensions, the virtual display is
48published with identity Windows topology rotation. For example, both portrait
49directions produce a native portrait surface rather than applying another
50width/height swap. Content rotation, if needed by a future streaming backend,
51must be an explicit renderer operation rather than an implicit display-mode
52rotation.
53
54For each ready group, the tray starts a separate managed Sunshine instance bound
55to that group's brace GUID. Instances use independent port families, so several
56virtual desktops can be streamed at the same time without rewriting the global
57Sunshine configuration or interrupting another group. The tray exposes the
58stream-only instances' LAN address and Web panel. Stopping the mapping also
59stops every instance that SBMS created. Moonlight pairing and connection still
60happen from the client device.
61
62At plan start, the tray projects Windows Desktop Duplication consumers as one
63process per managed Sunshine instance plus one process when any mirror renderer
64is present. If that total exceeds Windows' four-process DDA limit, the entire
65Sunshine batch starts with the WGC capture backend; otherwise Sunshine keeps its
66automatic backend selection. This is a runtime launch override and is not
67written into the global or per-instance Sunshine configuration.
68
69The projection covers only processes owned by the current SBMS plan; Windows
70does not expose a reliable list of external DDA consumers such as OBS or another
71Sunshine installation. Sunshine's WGC selection also does not change the SBMS
72mirror renderer: its Desktop Duplication dirty/move-rectangle copy path remains
73enabled independently.
74
75## JSON interface
76
77The CLI provides a GUI-independent validation and execution surface:
78
79```text
80sbms plan validate plan.json
81sbms plan run plan.json
82sbms plan run plan.json --hold-ms 30000
83```
84
85Example with one local mirror and one streaming desktop:
86
87```json
88{
89 "groups": [
90 {
91 "id": 0,
92 "mode": {
93 "width": 3840,
94 "height": 2160,
95 "refresh_numerator": 240,
96 "refresh_denominator": 1
97 },
98 "route": {
99 "kind": "mirror",
100 "target": "\\\\?\\DISPLAY#..."
101 }
102 },
103 {
104 "id": 1,
105 "mode": {
106 "width": 2560,
107 "height": 1440,
108 "refresh_numerator": 120,
109 "refresh_denominator": 1
110 },
111 "route": {
112 "kind": "stream_only"
113 }
114 }
115 ]
116}
117```
118
119The tray UI persists the complete ordered group list in
120the active profile in `%LOCALAPPDATA%\SBMS\config-profiles-v1.json` and builds
121one `MappingPlan` from it.
122Mirror and stream-only routes keep independent display, sizing, mode, refresh,
123aspect-ratio and rotation settings. The selected tab is persisted as a group
124ID. A valid legacy `config-v1.json` is imported once as mirror group
125`Output 1`; the old file is retained.
126
127The compatibility commands `sbms map` and `sbms config set-target` operate on
128`Output 1` only. They preserve every other configured group.
129