1#![expect(clippy::ref_option_ref)]
4
5use bitflags::bitflags;
6use derive_more::Debug;
7use serde::{Serialize, ser::SerializeStruct};
8use serde_with::skip_serializing_none;
9
10use crate::common::FlagsDebug;
11
12pub mod canvases;
13pub mod config;
14pub mod custom;
15pub mod filters;
16pub mod general;
17pub mod hotkeys;
18pub(crate) mod ids;
19pub mod inputs;
20pub(crate) mod media_inputs;
21pub(crate) mod outputs;
22pub mod profiles;
23pub(crate) mod recording;
24pub(crate) mod replay_buffer;
25pub(crate) mod scene_collections;
26pub mod scene_items;
27pub mod scenes;
28pub mod sources;
29pub(crate) mod streaming;
30pub(crate) mod transitions;
31pub mod ui;
32pub(crate) mod virtual_cam;
33
34pub(crate) enum ClientRequest<'a> {
35 Identify(Identify),
39 Reidentify(Reidentify),
41 Request(Request<'a>),
43 #[allow(dead_code)]
46 RequestBatch(RequestBatch<'a>),
47}
48
49impl Serialize for ClientRequest<'_> {
50 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
51 where
52 S: serde::Serializer,
53 {
54 #[derive(Clone, Copy, Serialize)]
55 #[serde(into = "u8")]
56 #[repr(u8)]
57 enum OpCode {
58 Identify = 1,
61 Reidentify = 3,
64 Request = 6,
66 RequestBatch = 8,
68 }
69
70 impl From<OpCode> for u8 {
71 fn from(value: OpCode) -> Self {
72 value as Self
73 }
74 }
75
76 fn write_state<S>(serializer: S, op: OpCode, d: &impl Serialize) -> Result<S::Ok, S::Error>
77 where
78 S: serde::Serializer,
79 {
80 let mut state = serializer.serialize_struct("ClientRequest", 2)?;
81 state.serialize_field("op", &op)?;
82 state.serialize_field("d", d)?;
83 state.end()
84 }
85
86 match self {
87 Self::Identify(value) => write_state(serializer, OpCode::Identify, value),
88 Self::Reidentify(value) => write_state(serializer, OpCode::Reidentify, value),
89 Self::Request(value) => write_state(serializer, OpCode::Request, value),
90 Self::RequestBatch(value) => write_state(serializer, OpCode::RequestBatch, value),
91 }
92 }
93}
94
95#[skip_serializing_none]
99#[derive(Serialize)]
100pub(crate) struct Identify {
101 #[serde(rename = "rpcVersion")]
103 pub rpc_version: u32,
104 #[serde(rename = "authentication")]
105 pub authentication: Option<String>,
106 #[serde(rename = "eventSubscriptions")]
110 pub event_subscriptions: Option<EventSubscription>,
111}
112
113#[skip_serializing_none]
115#[derive(Serialize)]
116pub(crate) struct Reidentify {
117 #[serde(rename = "eventSubscriptions")]
118 pub event_subscriptions: Option<EventSubscription>,
119}
120
121#[derive(Serialize)]
123pub(crate) struct Request<'a> {
124 #[serde(rename = "requestId")]
125 pub request_id: &'a str,
126 #[serde(flatten)]
127 pub ty: RequestType<'a>,
128}
129
130#[skip_serializing_none]
133#[derive(Serialize)]
134pub(crate) struct RequestBatch<'a> {
135 #[serde(rename = "requestId")]
136 pub request_id: &'a str,
137 #[serde(rename = "haltOnFailure")]
141 pub halt_on_failure: Option<bool>,
142 #[serde(rename = "requests")]
143 pub requests: &'a [RequestType<'a>],
144 #[serde(rename = "executionType")]
145 pub execution_type: Option<ExecutionType>,
146}
147
148#[derive(Clone, Copy, Default, Eq, Hash, Ord, PartialEq, PartialOrd, Debug, Serialize)]
151#[cfg_attr(
152 feature = "test-integration",
153 derive(serde::Deserialize),
154 serde(from = "u32")
155)]
156#[serde(into = "u32")]
157pub struct EventSubscription(#[debug("{:?}", FlagsDebug(self))] u32);
158
159bitflags! {
160 impl EventSubscription: u32 {
163 const NONE = 0;
165 const GENERAL = 1 << 0;
167 const CONFIG = 1 << 1;
169 const SCENES = 1 << 2;
171 const INPUTS = 1 << 3;
173 const TRANSITIONS = 1 << 4;
175 const FILTERS = 1 << 5;
177 const OUTPUTS = 1 << 6;
179 const SCENE_ITEMS = 1 << 7;
181 const MEDIA_INPUTS = 1 << 8;
183 const VENDORS = 1 << 9;
187 const UI = 1 << 10;
189 const CANVASES = 1 << 11;
191
192 const ALL = Self::GENERAL.bits()
194 | Self::CONFIG.bits()
195 | Self::SCENES.bits()
196 | Self::INPUTS.bits()
197 | Self::TRANSITIONS.bits()
198 | Self::FILTERS.bits()
199 | Self::OUTPUTS.bits()
200 | Self::SCENE_ITEMS.bits()
201 | Self::MEDIA_INPUTS.bits()
202 | Self::VENDORS.bits()
203 | Self::UI.bits()
204 | Self::CANVASES.bits();
205
206 const INPUT_VOLUME_METERS = 1 << 16;
210 const INPUT_ACTIVE_STATE_CHANGED = 1 << 17;
214 const INPUT_SHOW_STATE_CHANGED = 1 << 18;
218 const SCENE_ITEM_TRANSFORM_CHANGED = 1 << 19;
222
223 }
224}
225
226impl From<EventSubscription> for u32 {
227 fn from(value: EventSubscription) -> Self {
228 value.bits()
229 }
230}
231
232#[cfg(feature = "test-integration")]
233impl From<u32> for EventSubscription {
234 fn from(value: u32) -> Self {
235 Self::from_bits_truncate(value)
236 }
237}
238
239#[allow(dead_code)]
240#[derive(Clone, Copy, Serialize)]
241#[serde(into = "i8")]
242#[repr(i8)]
243pub(crate) enum ExecutionType {
244 None = -1,
246 SerialRealtime = 0,
248 SerialFrame = 1,
251 Parallel = 2,
254}
255
256impl From<ExecutionType> for i8 {
257 fn from(value: ExecutionType) -> Self {
258 value as Self
259 }
260}
261
262pub(crate) enum RequestType<'a> {
263 Canvases(self::canvases::Request),
264 Config(self::config::Request<'a>),
265 Filters(self::filters::Request<'a>),
266 General(self::general::Request<'a>),
267 Hotkeys(self::hotkeys::Request<'a>),
268 Inputs(self::inputs::Request<'a>),
269 MediaInputs(self::media_inputs::Request<'a>),
270 Outputs(self::outputs::Request<'a>),
271 Profiles(self::profiles::Request<'a>),
272 Recording(self::recording::Request<'a>),
273 ReplayBuffer(self::replay_buffer::Request),
274 SceneCollections(self::scene_collections::Request<'a>),
275 SceneItems(self::scene_items::Request<'a>),
276 Scenes(self::scenes::Request<'a>),
277 Sources(self::sources::Request<'a>),
278 Streaming(self::streaming::Request<'a>),
279 Transitions(self::transitions::Request<'a>),
280 Ui(self::ui::Request<'a>),
281 VirtualCam(self::virtual_cam::Request),
282}
283
284impl Serialize for RequestType<'_> {
285 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
286 where
287 S: serde::Serializer,
288 {
289 match self {
290 Self::Canvases(req) => req.serialize(serializer),
291 Self::Config(req) => req.serialize(serializer),
292 Self::Filters(req) => req.serialize(serializer),
293 Self::General(req) => req.serialize(serializer),
294 Self::Hotkeys(req) => req.serialize(serializer),
295 Self::Inputs(req) => req.serialize(serializer),
296 Self::MediaInputs(req) => req.serialize(serializer),
297 Self::Outputs(req) => req.serialize(serializer),
298 Self::Profiles(req) => req.serialize(serializer),
299 Self::Recording(req) => req.serialize(serializer),
300 Self::ReplayBuffer(req) => req.serialize(serializer),
301 Self::SceneCollections(req) => req.serialize(serializer),
302 Self::SceneItems(req) => req.serialize(serializer),
303 Self::Scenes(req) => req.serialize(serializer),
304 Self::Sources(req) => req.serialize(serializer),
305 Self::Streaming(req) => req.serialize(serializer),
306 Self::Transitions(req) => req.serialize(serializer),
307 Self::Ui(req) => req.serialize(serializer),
308 Self::VirtualCam(req) => req.serialize(serializer),
309 }
310 }
311}