diff --git a/src/protocol.rs b/src/protocol.rs index 3c2fa1f..5229727 100644 --- a/src/protocol.rs +++ b/src/protocol.rs @@ -19,6 +19,8 @@ pub enum MessageInbound { KeyboardEvent(KeyboardEvent), GetCapturableList, Config(ClientConfiguration), + PauseVideo, + ResumeVideo, } #[derive(Serialize, Deserialize, Debug)] diff --git a/src/websocket.rs b/src/websocket.rs index a80d6a4..8387ab1 100644 --- a/src/websocket.rs +++ b/src/websocket.rs @@ -29,6 +29,8 @@ struct VideoConfig { enum VideoCommands { Start(VideoConfig), + Pause, + Resume, } fn send_message(sender: &mut S, message: MessageOutbound) @@ -109,6 +111,12 @@ impl WeylusClientHandler { MessageInbound::KeyboardEvent(event) => self.process_keyboard_event(&event), MessageInbound::GetCapturableList => self.send_capturable_list(), MessageInbound::Config(config) => self.update_config(config), + MessageInbound::PauseVideo => { + self.video_sender.send(VideoCommands::Pause).unwrap() + } + MessageInbound::ResumeVideo => { + self.video_sender.send(VideoCommands::Resume).unwrap() + } }, Err(err) => { warn!("Failed to read message {err}!"); @@ -276,15 +284,16 @@ fn handle_video( mut sender: S, encoder_options: EncoderOptions, ) { - const EFFECTIVE_INIFINIT: Duration = Duration::from_secs(3600 * 24 * 365 * 200); + const EFFECTIVE_INIFINITY: Duration = Duration::from_secs(3600 * 24 * 365 * 200); let mut recorder: Option> = None; let mut video_encoder: Option> = None; let mut max_width = 1920; let mut max_height = 1080; - let mut frame_duration = EFFECTIVE_INIFINIT; + let mut frame_duration = EFFECTIVE_INIFINITY; let mut last_frame = Instant::now(); + let mut paused = false; loop { let now = Instant::now(); @@ -298,7 +307,7 @@ fn handle_video( debug!("Dropped {frames_passed} frame(s)!"); } - match receiver.recv_timeout(timeout) { + match receiver.recv_timeout(if paused { EFFECTIVE_INIFINITY } else { timeout }) { Ok(VideoCommands::Start(config)) => { #[allow(unused_assignments)] { @@ -336,9 +345,15 @@ fn handle_video( frame_duration = if d.is_finite() { Duration::from_secs_f64(d) } else { - EFFECTIVE_INIFINIT + EFFECTIVE_INIFINITY }; - frame_duration = frame_duration.min(EFFECTIVE_INIFINIT); + frame_duration = frame_duration.min(EFFECTIVE_INIFINITY); + } + Ok(VideoCommands::Pause) => { + paused = true; + } + Ok(VideoCommands::Resume) => { + paused = false; } Err(RecvTimeoutError::Timeout) => { if recorder.is_none() { diff --git a/ts/lib.ts b/ts/lib.ts index a3d82a8..ae8a6e5 100644 --- a/ts/lib.ts +++ b/ts/lib.ts @@ -82,25 +82,6 @@ function fresh_canvas() { return canvas; } -function toggle_energysaving(energysaving: boolean) { - let canvas = fresh_canvas(); - if (energysaving) { - let ctx = canvas.getContext("2d"); - ctx.fillStyle = "#000"; - ctx.fillRect(0, 0, canvas.width, canvas.height); - } - - if (settings) { - if (energysaving) { - settings.checks.get("enable_video").checked = false; - settings.checks.get("enable_video").disabled = true; - settings.checks.get("enable_video").dispatchEvent(new Event("change")); - } else - settings.checks.get("enable_video").disabled = false; - new PointerHandler(settings.webSocket); - } -} - class Settings { webSocket: WebSocket; checks: Map; @@ -175,9 +156,15 @@ class Settings { }; this.checks.get("enable_video").onchange = (e) => { - document.getElementById("video").classList.toggle("vanish", !(e.target as HTMLInputElement).checked); - document.getElementById("canvas").classList.toggle("vanish", (e.target as HTMLInputElement).checked); + let enabled = (e.target as HTMLInputElement).checked; + document.getElementById("video").classList.toggle("vanish", !enabled); + document.getElementById("canvas").classList.toggle("vanish", enabled); this.save_settings(); + if (enabled) { + this.webSocket.send('"ResumeVideo"'); + } else { + this.webSocket.send('"PauseVideo"'); + } } let upd_pointer = () => { @@ -190,7 +177,7 @@ class Settings { this.checks.get("energysaving").onchange = (e) => { this.save_settings(); - toggle_energysaving((e.target as HTMLInputElement).checked); + this.toggle_energysaving((e.target as HTMLInputElement).checked); }; this.frame_rate_input.onchange = () => this.save_settings(); @@ -280,7 +267,7 @@ class Settings { } if (this.checks.get("energysaving").checked) { - toggle_energysaving(true); + this.toggle_energysaving(true); } let client_name = settings["client_name"]; @@ -333,6 +320,28 @@ class Settings { // Can't find the window, so don't select anything this.capturable_select.value = ""; } + + toggle_energysaving(energysaving: boolean) { + let canvas = fresh_canvas(); + if (energysaving) { + let ctx = canvas.getContext("2d"); + ctx.fillStyle = "#000"; + ctx.fillRect(0, 0, canvas.width, canvas.height); + } + + if (energysaving) { + this.checks.get("enable_video").checked = false; + this.checks.get("enable_video").disabled = true; + this.checks.get("enable_video").dispatchEvent(new Event("change")); + } else + this.checks.get("enable_video").disabled = false; + if (settings) + new PointerHandler(this.webSocket); + } + + video_enabled(): boolean { + return this.checks.get("enable_video").checked; + } } let settings: Settings; @@ -931,7 +940,18 @@ function init() { window.onunload = () => { webSocket.close(); } webSocket.onopen = function(event) { webSocket.send('"GetCapturableList"'); + if (!settings.video_enabled()) + webSocket.send('"PauseVideo"'); + settings.send_server_config(); + + document.onvisibilitychange = () => { + if (document.hidden) { + webSocket.send('"PauseVideo"'); + } else if (settings.video_enabled()) { + webSocket.send('"ResumeVideo"'); + } + }; } frame_rate_stats(); }