gled_protocol/message.rs
1//! The messages of a connection between a remote user interface and the
2//! engine, over a WebSocket. The interface opens with `Hello`; the server
3//! answers `Welcome` or `Rejected`, then sends the state whenever it changes.
4
5use std::sync::Arc;
6
7use gled_model::input::event::InputEvent;
8use gled_model::timing::BeatState;
9use serde::{Deserialize, Serialize};
10
11use crate::assets::{AnyAsset, AssetChanges};
12use crate::bytes::SharedBytes;
13use crate::midi::MidiMonitorEvent;
14use crate::project_update::ProjectUpdate;
15use crate::state::{ClientInput, EngineEvent, EngineState, RenderStats, SoundSnapshot};
16
17/// Changes whenever a message changes incompatibly. Both ends must agree.
18///
19/// 2: the patch replaced the SVG and the groups (`ProjectUpdate::Changed`,
20/// `UiAction::SetProjectPatch`, `SetSceneEffectLayout`).
21/// 3: pictures travel through the engine (`ClientInput::SavePicture`,
22/// `RequestPicture`, `EngineEvent::Picture`).
23pub const PROTOCOL_VERSION: u32 = 3;
24
25/// The optional streams an interface can ask for. All are off until it
26/// subscribes, so a hidden page costs nothing.
27#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
28#[serde(default)]
29pub struct Subscriptions {
30 pub preview: bool,
31 pub sound: bool,
32 /// New input events (keys, gamepad, Art-Net), for assigning inputs.
33 pub input_events: bool,
34 /// The MIDI monitor and the messages MIDI learn captured.
35 pub midi: bool,
36}
37
38/// From a user interface to the server.
39#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
40pub enum ClientMessage {
41 Hello {
42 protocol_version: u32,
43 /// The interface's gled version, for the logs.
44 app_version: String,
45 },
46 Input(ClientInput),
47 /// Which of the optional streams this interface wants.
48 Subscribe(Subscriptions),
49 /// Asks for a `Pong` with the same number, to measure the round trip.
50 Ping(u64),
51}
52
53/// From the server to a user interface.
54#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
55pub enum ServerMessage {
56 Welcome {
57 client_id: u64,
58 /// The server's gled version.
59 app_version: String,
60 },
61 /// The connection is closed after this.
62 Rejected {
63 reason: String,
64 },
65 State {
66 state: Arc<EngineState>,
67 /// The number of the newest action of this interface applied.
68 applied_sequence: u64,
69 },
70 /// What changed since the last `State` or `Update`: the state without
71 /// its project, which comes as a patch.
72 Update {
73 /// The state with `project: None`.
74 state: Arc<EngineState>,
75 project: ProjectUpdate,
76 applied_sequence: u64,
77 },
78 /// The timing, when nothing else changed since the last `State`.
79 Timing {
80 beat: BeatState,
81 render: RenderStats,
82 },
83 /// Every asset, sent once after `Welcome`.
84 Assets(Vec<AnyAsset>),
85 /// Assets that changed since `Assets` or the last `AssetsChanged`.
86 AssetsChanged(AssetChanges),
87 /// The LED output as rendered, for the preview: three bytes per lamp,
88 /// 512 bytes per universe in the order of `OutputConfig::universes`.
89 /// Only sent to interfaces that subscribed to it.
90 Preview(SharedBytes),
91 /// Sound levels, at most 30 times a second, to interfaces that subscribed.
92 Sound(Arc<SoundSnapshot>),
93 /// Input events that happened since the last of these, to interfaces
94 /// that subscribed.
95 InputEvents(Vec<InputEvent>),
96 /// MIDI traffic since the last of these, to interfaces that subscribed.
97 MidiMonitor(Vec<MidiMonitorEvent>),
98 /// Messages MIDI learn captured since the last of these.
99 MidiLearn(Vec<[u8; 3]>),
100 Event(EngineEvent),
101 Pong(u64),
102}