gled-protocol 2.31.0

What gled's user interfaces and its engine send each other
Documentation
//! The messages of a connection between a remote user interface and the
//! engine, over a WebSocket. The interface opens with `Hello`; the server
//! answers `Welcome` or `Rejected`, then sends the state whenever it changes.

use std::sync::Arc;

use gled_model::input::event::InputEvent;
use gled_model::timing::BeatState;
use serde::{Deserialize, Serialize};

use crate::assets::{AnyAsset, AssetChanges};
use crate::bytes::SharedBytes;
use crate::midi::MidiMonitorEvent;
use crate::project_update::ProjectUpdate;
use crate::state::{ClientInput, EngineEvent, EngineState, RenderStats, SoundSnapshot};

/// Changes whenever a message changes incompatibly. Both ends must agree.
///
/// 2: the patch replaced the SVG and the groups (`ProjectUpdate::Changed`,
/// `UiAction::SetProjectPatch`, `SetSceneEffectLayout`).
pub const PROTOCOL_VERSION: u32 = 2;

/// The optional streams an interface can ask for. All are off until it
/// subscribes, so a hidden page costs nothing.
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
#[serde(default)]
pub struct Subscriptions {
    pub preview: bool,
    pub sound: bool,
    /// New input events (keys, gamepad, Art-Net), for assigning inputs.
    pub input_events: bool,
    /// The MIDI monitor and the messages MIDI learn captured.
    pub midi: bool,
}

/// From a user interface to the server.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum ClientMessage {
    Hello {
        protocol_version: u32,
        /// The interface's gled version, for the logs.
        app_version: String,
    },
    Input(ClientInput),
    /// Which of the optional streams this interface wants.
    Subscribe(Subscriptions),
    /// Asks for a `Pong` with the same number, to measure the round trip.
    Ping(u64),
}

/// From the server to a user interface.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum ServerMessage {
    Welcome {
        client_id: u64,
        /// The server's gled version.
        app_version: String,
    },
    /// The connection is closed after this.
    Rejected {
        reason: String,
    },
    State {
        state: Arc<EngineState>,
        /// The number of the newest action of this interface applied.
        applied_sequence: u64,
    },
    /// What changed since the last `State` or `Update`: the state without
    /// its project, which comes as a patch.
    Update {
        /// The state with `project: None`.
        state: Arc<EngineState>,
        project: ProjectUpdate,
        applied_sequence: u64,
    },
    /// The timing, when nothing else changed since the last `State`.
    Timing {
        beat: BeatState,
        render: RenderStats,
    },
    /// Every asset, sent once after `Welcome`.
    Assets(Vec<AnyAsset>),
    /// Assets that changed since `Assets` or the last `AssetsChanged`.
    AssetsChanged(AssetChanges),
    /// The LED output as rendered, for the preview: three bytes per lamp,
    /// 512 bytes per universe in the order of `OutputConfig::universes`.
    /// Only sent to interfaces that subscribed to it.
    Preview(SharedBytes),
    /// Sound levels, at most 30 times a second, to interfaces that subscribed.
    Sound(Arc<SoundSnapshot>),
    /// Input events that happened since the last of these, to interfaces
    /// that subscribed.
    InputEvents(Vec<InputEvent>),
    /// MIDI traffic since the last of these, to interfaces that subscribed.
    MidiMonitor(Vec<MidiMonitorEvent>),
    /// Messages MIDI learn captured since the last of these.
    MidiLearn(Vec<[u8; 3]>),
    Event(EngineEvent),
    Pong(u64),
}