Skip to main content

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