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.
文件
../ architecture.md2.3 KBconfiguration.md4.9 KBgeometry.md2.4 KBlogical-desktop-size-observation.md3.4 KBmapping-plan.md4.9 KBdocs/mapping-plan.md4.9 KB
1
# Mapping plan interface2
3
The Rust core supports one process-level mapping plan containing up to sixteen4
groups. A group ID is a stable zero-based IDD connector index (`0..=15`); list5
order is not identity.6
7
```rust8
MappingPlan::new(groups)?;9
MappingSession::start_plan(plan)?;10
MappingSession::start_plan_with_reporter(plan, reporter)?;11
session.groups();12
session.stop()?;13
```14
15
`MappingRoute::Mirror { target }` creates a virtual display, migrates windows16
from the physical target, and starts the GPU mirror and input endpoint.17
`MappingRoute::StreamOnly` only creates and mode-confirms the virtual display.18
It does not create a renderer, migrate windows, or capture input. This is the19
route intended for Sunshine or another external capturer.20
21
Startup rejects an empty plan, more than sixteen groups, duplicate/out-of-range22
group IDs, duplicate physical targets, invalid modes, missing targets, cloned23
GDI targets, and attempts to use an SBMS virtual display as a physical target.24
The plan is atomic: a failure rolls back all groups and restores physical25
topology once. Runtime insertion, deletion, or mutation of individual groups is26
not part of this interface; stop the plan and start a replacement plan.27
28
Each `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 for38
SBMS configuration and the brace GUID for Sunshine's `output_name`.39
40
Each group may also specify `rotation` as `deg0`, `deg90`, `deg180`, or41
`deg270`; omitted values remain `deg0`. `mode.width` and `mode.height` are the42
final native desktop dimensions published by the IDD. SBMS does not swap a43
portrait mode back to landscape: `1800x2880` remains a native `1800x2880`44
display so applications can detect the portrait surface directly.45
46
The rotation value remains the user's orientation and sizing input. Once those47
inputs have produced the final native dimensions, the virtual display is48
published with identity Windows topology rotation. For example, both portrait49
directions produce a native portrait surface rather than applying another50
width/height swap. Content rotation, if needed by a future streaming backend,51
must be an explicit renderer operation rather than an implicit display-mode52
rotation.53
54
For each ready group, the tray starts a separate managed Sunshine instance bound55
to that group's brace GUID. Instances use independent port families, so several56
virtual desktops can be streamed at the same time without rewriting the global57
Sunshine configuration or interrupting another group. The tray exposes the58
stream-only instances' LAN address and Web panel. Stopping the mapping also59
stops every instance that SBMS created. Moonlight pairing and connection still60
happen from the client device.61
62
At plan start, the tray projects Windows Desktop Duplication consumers as one63
process per managed Sunshine instance plus one process when any mirror renderer64
is present. If that total exceeds Windows' four-process DDA limit, the entire65
Sunshine batch starts with the WGC capture backend; otherwise Sunshine keeps its66
automatic backend selection. This is a runtime launch override and is not67
written into the global or per-instance Sunshine configuration.68
69
The projection covers only processes owned by the current SBMS plan; Windows70
does not expose a reliable list of external DDA consumers such as OBS or another71
Sunshine installation. Sunshine's WGC selection also does not change the SBMS72
mirror renderer: its Desktop Duplication dirty/move-rectangle copy path remains73
enabled independently.74
75
## JSON interface76
77
The CLI provides a GUI-independent validation and execution surface:78
79
```text80
sbms plan validate plan.json81
sbms plan run plan.json82
sbms plan run plan.json --hold-ms 3000083
```84
85
Example with one local mirror and one streaming desktop:86
87
```json88
{89
"groups": [90
{91
"id": 0,92
"mode": {93
"width": 3840,94
"height": 2160,95
"refresh_numerator": 240,96
"refresh_denominator": 197
},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": 1110
},111
"route": {112
"kind": "stream_only"113
}114
}115
]116
}117
```118
119
The tray UI persists the complete ordered group list in120
the active profile in `%LOCALAPPDATA%\SBMS\config-profiles-v1.json` and builds121
one `MappingPlan` from it.122
Mirror and stream-only routes keep independent display, sizing, mode, refresh,123
aspect-ratio and rotation settings. The selected tab is persisted as a group124
ID. A valid legacy `config-v1.json` is imported once as mirror group125
`Output 1`; the old file is retained.126
127
The compatibility commands `sbms map` and `sbms config set-target` operate on128
`Output 1` only. They preserve every other configured group.129