From 056bdf6db6576f8e29d8942b722abb3417e38cdf Mon Sep 17 00:00:00 2001 From: ochibani <11yzyv86j@relay.firefox.com> Date: Sat, 25 Jan 2025 06:21:36 +0200 Subject: [PATCH] update ffmpeg_window --- core/Cargo.toml | 5 +- core/src/ffmpeg_linux.rs | 46 ++++-- core/src/ffmpeg_windows.rs | 310 +++++++++++++++++-------------------- core/src/lib.rs | 9 +- gui/src/ui.rs | 53 +++++-- 5 files changed, 223 insertions(+), 200 deletions(-) diff --git a/core/Cargo.toml b/core/Cargo.toml index 9d1455c..918bd7b 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -14,8 +14,11 @@ async-std = {version = "1.12.0", features = ["attributes"]} chrono = { version = "0.4.19", optional = true } ffmpeg-sidecar = "2.0.5" glib = { version = "0.10.3", optional = true } -gstreamer = "0.23.4" open = "5.1.4" subprocess = {version = "0.2.6", optional = true } tempfile = "3.10.1" zbus = "5.3.0" + +# FreeBSD/Linux-only dependency +[target.'cfg(not(windows))'.dependencies] +gstreamer = "0.23.4" diff --git a/core/src/ffmpeg_linux.rs b/core/src/ffmpeg_linux.rs index 3c1d31f..73069f3 100644 --- a/core/src/ffmpeg_linux.rs +++ b/core/src/ffmpeg_linux.rs @@ -24,6 +24,7 @@ use crate::utils::{is_video_record, is_wayland, RecordMode}; use crate::utils::{is_input_audio_record, is_output_audio_record, is_valid}; #[cfg(feature = "gtk")] use crate::utils::validate_video_file; +#[cfg(feature = "gtk")] use crate::wayland_linux::{CursorModeTypes, RecordTypes, WaylandRecorder}; #[cfg(feature = "cmd")] @@ -80,7 +81,7 @@ pub struct Ffmpeg { impl Ffmpeg { // Start video recording pub fn start_video(&mut self, x: u16, y: u16, width: u16, height: u16, mode: RecordMode) -> Result<()> { - //if mode == RecordMode::Window && !self.follow_mouse.is_active() { + //if let RecordMode::Window == mode && !self.follow_mouse.is_active() { // TODO pulse = gstreamer for video && add to cmd linux + add convert function to gstreamer ouput //} else { let display = format!("{}+{},{}", @@ -94,7 +95,7 @@ impl Ffmpeg { self.width = Some(width); self.height = Some(height); - // Record video to tmp if audio record enabled + // Record video to tmp if output is GIF if !self.audio_input_id.is_empty() || !self.audio_output_id.is_empty() || self.output == "gif" @@ -668,6 +669,9 @@ impl Ffmpeg { Err(error) => { if self.output == "gif" { self.clean()?; + } else { + self.temp_video_filename = self.saved_filename.clone(); + self.clean()?; } return Err(Error::msg(format!("{}", error))); }, @@ -730,11 +734,20 @@ impl Ffmpeg { pub fn stop_input_audio(&mut self) -> Result<()> { // Quit the process to stop recording if self.input_audio_process.is_some() { - self.input_audio_process - .clone() - .ok_or_else(|| anyhow!("Not exiting the input audio recording process successfully."))? - .borrow_mut() - .quit()?; + match self.input_audio_process + .clone() + .ok_or_else(|| anyhow!("Not exiting the input audio recording process successfully."))? + .borrow_mut() + .quit() { + Ok(_) => { + // Continue + }, + Err(error) => { + self.temp_video_filename = self.saved_filename.clone(); + self.clean()?; + return Err(Error::msg(format!("{}", error))); + }, + } } Ok(()) } @@ -766,11 +779,20 @@ impl Ffmpeg { pub fn stop_output_audio(&mut self) -> Result<()> { // Quit the process to stop recording if self.output_audio_process.is_some() { - self.output_audio_process - .clone() - .ok_or_else(|| anyhow!("Not exiting the output audio recording process successfully."))? - .borrow_mut() - .quit()?; + match self.output_audio_process + .clone() + .ok_or_else(|| anyhow!("Not exiting the output audio recording process successfully."))? + .borrow_mut() + .quit() { + Ok(_) => { + // Continue + }, + Err(error) => { + self.temp_video_filename = self.saved_filename.clone(); + self.clean()?; + return Err(Error::msg(format!("{}", error))); + }, + } } Ok(()) } diff --git a/core/src/ffmpeg_windows.rs b/core/src/ffmpeg_windows.rs index 501e802..fd5fb4c 100644 --- a/core/src/ffmpeg_windows.rs +++ b/core/src/ffmpeg_windows.rs @@ -4,19 +4,25 @@ use adw::gtk::{CheckButton, ComboBoxText, Entry, FileChooserNative, SpinButton}; use adw::gtk::prelude::*; use anyhow::{anyhow, Error, Result}; #[cfg(feature = "gtk")] -use chrono::Utc; +use chrono::{Datelike, Timelike, Utc}; use ffmpeg_sidecar::child::FfmpegChild; use ffmpeg_sidecar::command::FfmpegCommand; use tempfile; -use std::{cell::RefCell, time::Instant}; +use std::cell::RefCell; use std::path::Path; #[cfg(feature = "gtk")] use std::path::PathBuf; use std::rc::Rc; use std::thread::sleep; use std::time::Duration; +#[cfg(feature = "cmd")] +use std::time::Instant; -use crate::utils::{is_input_audio_record, is_output_audio_record, is_valid, is_video_record, RecordMode}; +use crate::utils::{is_video_record, RecordMode}; +#[cfg(feature = "cmd")] +use crate::utils::{is_input_audio_record, is_output_audio_record, is_valid}; +#[cfg(feature = "gtk")] +use crate::utils::validate_video_file; #[cfg(feature = "cmd")] #[derive(Clone)] @@ -28,7 +34,6 @@ pub struct Ffmpeg { pub temp_input_audio_filename: String, pub temp_output_audio_filename: String, pub temp_video_filename: String, - pub window_title: String, pub height: Option, pub input_audio_process: Option>>, pub output_audio_process: Option>>, @@ -49,10 +54,7 @@ pub struct Ffmpeg { pub audio_output_id: String, pub filename: (FileChooserNative, Entry, ComboBoxText), pub output: String, - pub temp_input_audio_filename: String, - pub temp_output_audio_filename: String, pub temp_video_filename: String, - pub window_title: String, pub saved_filename: String, pub height: Option, pub input_audio_process: Option>>, @@ -73,11 +75,11 @@ pub struct Ffmpeg { #[cfg(feature = "cmd")] impl Ffmpeg { // Start video recording - pub fn start_video(&mut self, x: u16, y: u16, width: u16, height: u16, mode: RecordMode) -> Result<()> { + pub fn start_video(&mut self, x: u16, y: u16, width: u16, height: u16, mode: RecordMode, title: String) -> Result<()> { let display = match mode { RecordMode::Area => "desktop", RecordMode::Screen => "desktop", - RecordMode::Window => &format!("title={}", &self.window_title), + RecordMode::Window => &format!("title={}", title), }; let mut ffmpeg_command = FfmpegCommand::new(); let format = "gdigrab"; @@ -440,6 +442,7 @@ impl Ffmpeg { impl Ffmpeg { // Get file name pub fn get_filename(&mut self) -> Result<()> { + let utc_now = Utc::now; self.saved_filename = self.filename .0 @@ -450,7 +453,14 @@ impl Ffmpeg { .join(PathBuf::from(format!( "{}.{}", if self.filename.1.text().to_string().trim().eq("") { - Utc::now().to_string().replace(" UTC", "").replace(' ', "-") + format!("{}-{:02}-{:02}_{:02}-{:02}-{:02}", + utc_now().year(), + utc_now().month0(), + utc_now().day0(), + utc_now().hour(), + utc_now().minute(), + utc_now().second() + ) } else { self.filename.1.text().to_string().trim().to_string() }, @@ -463,11 +473,11 @@ impl Ffmpeg { } // Start video recording - pub fn start_video(&mut self, x: u16, y: u16, width: u16, height: u16, mode: RecordMode) -> Result<()> { + pub fn start_video(&mut self, x: u16, y: u16, width: u16, height: u16, mode: RecordMode, title: String) -> Result<()> { let display = match mode { RecordMode::Area => "desktop", RecordMode::Screen => "desktop", - RecordMode::Window => &format!("title={}", &self.window_title), + RecordMode::Window => &format!("title={}", title), }; let mut ffmpeg_command = FfmpegCommand::new(); let format = "gdigrab"; @@ -476,17 +486,9 @@ impl Ffmpeg { .ok_or_else(|| anyhow!("Failed to get file extension."))? .to_string_lossy().to_string(); - // Record video to tmp if audio record enabled - if !self.audio_input_id.active_id().ok_or_else(|| anyhow!("Failed to get audio input device ID."))? - .to_string().is_empty() - || !self.audio_output_id.is_empty() - || self.output == "gif" - { - let suffix = if self.output == "gif" { - ".mp4" - } else { - &format!(".{}", &self.output) - }; + // Record video to tmp if output is GIF + if self.output == "gif" { + let suffix = ".mp4"; let video_tempfile = tempfile::Builder::new().prefix(".ffmpeg-video-") .suffix(suffix) .tempfile()? @@ -494,6 +496,7 @@ impl Ffmpeg { self.temp_video_filename = Path::new(&video_tempfile.1).to_string_lossy() .to_string(); } + // Video format ffmpeg_command.format(format); @@ -525,6 +528,20 @@ impl Ffmpeg { // input ffmpeg_command.input(display); + // Record audio input + if self.audio_input_switch.is_active() { + ffmpeg_command.format("pulse") + .input(&self.audio_input_id.active_id() + .ok_or_else(|| anyhow!("Failed to get audio input ID."))? + ); + } + + // Record audio output + if self.audio_output_switch.is_active() { + ffmpeg_command.format("pulse") + .input(&self.audio_output_id); + } + // Disable bitrate if value is zero if self.video_record_bitrate.value() as u16 > 0 { ffmpeg_command.args([ @@ -533,13 +550,14 @@ impl Ffmpeg { ]); } - // tmp file - if self.audio_input_id.active_id().ok_or_else(|| anyhow!("Failed to get audio input device ID."))? - .to_string().is_empty() && - self.audio_output_id.is_empty() && - self.output != "gif" - { - ffmpeg_command.args(["-hls_flags", "temp_file"]); + // Disable audio bitrate if value is zero + if self.audio_input_switch.is_active() || self.audio_output_switch.is_active() { + if self.audio_record_bitrate.value() as u16 > 0 { + ffmpeg_command.args([ + "-b:a", + &format!("{}K", self.audio_record_bitrate.value() as u16), + ]); + } } // Remove metadate @@ -549,10 +567,7 @@ impl Ffmpeg { let saved_filename = self.saved_filename.clone(); ffmpeg_command.args([ { - if !self.audio_input_id.active_id().ok_or_else(|| anyhow!("Failed to get audio input device ID."))? - .to_string().is_empty() - || !self.audio_output_id.is_empty() - || self.output == "gif" + if self.output == "gif" { &self.temp_video_filename } else { @@ -575,29 +590,52 @@ impl Ffmpeg { pub fn stop_video(&mut self) -> Result<()> { // Quit the process to stop recording if self.video_process.is_some() { - self.video_process - .clone() - .ok_or_else(|| anyhow!("Not exiting the video recording process successfully."))? - .borrow_mut() - .quit()?; + match self.video_process + .clone() + .ok_or_else(|| anyhow!("Not exiting the video recording process successfully."))? + .borrow_mut() + .quit() { + Ok(_) => { + if self.output == "gif" { + match self.merge() { + Ok(_) => { + self.clean()?; + }, + Err(error) => { + self.clean()?; + return Err(Error::msg(format!("{}", error))); + } + } + } + }, + Err(error) => { + if self.output == "gif" { + self.clean()?; + } else { + self.temp_video_filename = self.saved_filename.clone(); + self.clean()?; + } + return Err(Error::msg(format!("{}", error))); + }, + } } Ok(()) } // Start audio input recording pub fn start_input_audio(&mut self) -> Result<()> { - let input_audio_tempfile = tempfile::Builder::new().prefix(".ffmpeg-audio-") - .suffix(".ogg") - .tempfile()? - .keep()?; - self.temp_input_audio_filename = Path::new(&input_audio_tempfile.1).to_string_lossy() - .to_string(); let mut ffmpeg_command = FfmpegCommand::new(); ffmpeg_command.format("dshow") .input(format!("audio=\"{}\"", &self.audio_input_id.active_text() .ok_or_else(|| anyhow!("Failed to get audio input source."))?) ) .format("ogg"); + if self.audio_output_switch.is_active() { + ffmpeg_command.format("pulse") + .input(&self.audio_output_id); + } + ffmpeg_command.format("ogg"); + // Disable bitrate if value is zero if self.audio_record_bitrate.value() as u16 > 0 { ffmpeg_command.args([ @@ -605,13 +643,14 @@ impl Ffmpeg { &format!("{}K", self.audio_record_bitrate.value() as u16), ]); } + // Remove metadate ffmpeg_command.args(["-map_metadata", "-1"]); - ffmpeg_command.arg(&self.temp_input_audio_filename); + ffmpeg_command.arg(&self.saved_filename); ffmpeg_command.overwrite(); // Sleep for delay - if !is_video_record(&self.temp_video_filename) { + if !self.video_switch.is_active() { sleep(Duration::from_secs(self.record_delay.value() as u64)); } @@ -624,34 +663,37 @@ impl Ffmpeg { pub fn stop_input_audio(&mut self) -> Result<()> { // Quit the process to stop recording if self.input_audio_process.is_some() { - self.input_audio_process - .clone() - .ok_or_else(|| anyhow!("Not exiting the input audio recording process successfully."))? - .borrow_mut() - .quit()?; + match self.input_audio_process + .clone() + .ok_or_else(|| anyhow!("Not exiting the input audio recording process successfully."))? + .borrow_mut() + .quit() { + Ok(_) => { + // Continue + }, + Err(error) => { + self.temp_video_filename = self.saved_filename.clone(); + self.clean()?; + return Err(Error::msg(format!("{}", error))); + }, + } } Ok(()) } // Start audio output recording pub fn start_output_audio(&mut self) -> Result<()> { - let output_audio_tempfile = tempfile::Builder::new().prefix(".ffmpeg-audio-") - .suffix(".ogg") - .tempfile()? - .keep()?; - self.temp_output_audio_filename = Path::new(&output_audio_tempfile.1).to_string_lossy() - .to_string(); let mut ffmpeg_command = FfmpegCommand::new(); ffmpeg_command.format("dshow") .input(format!("audio=\"{}\"", &self.audio_output_id)) .format("ogg"); // Remove metadate ffmpeg_command.args(["-map_metadata", "-1"]); - ffmpeg_command.arg(&self.temp_output_audio_filename); + ffmpeg_command.arg(&self.saved_filename); ffmpeg_command.overwrite(); // Sleep for delay - if !is_video_record(&self.temp_video_filename) && !is_input_audio_record(&self.temp_input_audio_filename) { + if !self.video_switch.is_active() && !self.audio_input_switch.is_active() { sleep(Duration::from_secs(self.record_delay.value() as u64)); } @@ -664,11 +706,20 @@ impl Ffmpeg { pub fn stop_output_audio(&mut self) -> Result<()> { // Quit the process to stop recording if self.output_audio_process.is_some() { - self.output_audio_process - .clone() - .ok_or_else(|| anyhow!("Not exiting the output audio recording process successfully."))? - .borrow_mut() - .quit()?; + match self.output_audio_process + .clone() + .ok_or_else(|| anyhow!("Not exiting the output audio recording process successfully."))? + .borrow_mut() + .quit() { + Ok(_) => { + // Continue + }, + Err(error) => { + self.temp_video_filename = self.saved_filename.clone(); + self.clean()?; + return Err(Error::msg(format!("{}", error))); + }, + } } Ok(()) } @@ -676,118 +727,39 @@ impl Ffmpeg { // Merge tmp to target format pub fn merge(&mut self) -> Result<()> { if is_video_record(&self.temp_video_filename) { - if self.output != "gif" { - // Validate video file integrity - let start_time = Instant::now(); - let duration = Duration::from_secs(60); - loop { - if is_valid(&self.temp_video_filename)? { - break; - } else if Instant::now().duration_since(start_time) >= duration { - return Err(Error::msg("Unable to validate tmp video file.")); + // Validate video file integrity + match validate_video_file(self.temp_video_filename.clone()) { + Ok(_) => { + // Convert MP4 to GIF + let filter = format!("fps={},scale={}:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse", + self.record_frames.value() as u16, + self.height.ok_or_else + (|| anyhow!("Unable to get height value"))?); + let ffmpeg_convert = format!("ffmpeg -i file:{} -filter_complex '{}' \ + -loop 0 {} -y", &self.temp_video_filename,filter, + &self.saved_filename + .clone()); + match std::process::Command::new("sh").arg("-c").arg(&ffmpeg_convert).output() { + Ok(_) => { + // Do nothing + }, + Err(error) => { + return Err(Error::msg(format!("{}", error))); + }, } - } - if is_input_audio_record(&self.temp_input_audio_filename) || - is_output_audio_record(&self.temp_output_audio_filename) { - let mut ffmpeg_command = FfmpegCommand::new(); - ffmpeg_command.input(&self.temp_video_filename); - ffmpeg_command.format("ogg"); - if is_input_audio_record(&self.temp_input_audio_filename) { - ffmpeg_command.input(&self.temp_input_audio_filename); - } - if is_output_audio_record(&self.temp_output_audio_filename) { - ffmpeg_command.input(&self.temp_output_audio_filename); - } - ffmpeg_command.args([ - "-c:a", - "aac", - &self.saved_filename.clone() - ]); - ffmpeg_command.overwrite() - .spawn()? - .wait()?; - } else { - std::fs::copy(&self.temp_video_filename, &self.saved_filename)?; - } - } else { - // Validate video file integrity - let start_time = Instant::now(); - let duration = Duration::from_secs(60); - loop { - if is_valid(&self.temp_video_filename)? { - break; - } else if Instant::now().duration_since(start_time) >= duration { - return Err(Error::msg("Unable to validate tmp video file.")); - } - } - // Convert MP4 to GIF - let filter = format!("fps={},scale={}:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse", - self.record_frames.value() as u16, - self.height.ok_or_else - (|| anyhow!("Unable to get height value"))?); - let ffmpeg_convert = format!("ffmpeg -i file:{} -filter_complex '{}' \ - -loop 0 {} -y", &self.temp_video_filename,filter, - &self.saved_filename - .clone()); - std::process::Command::new("sh").arg("-c").arg(&ffmpeg_convert).output()?; + }, + Err(error) => { + return Err(Error::msg(format!("{}", error))); + }, } - } else if is_input_audio_record(&self.temp_input_audio_filename) { - // Validate audio file integrity - let start_time = Instant::now(); - let duration = Duration::from_secs(60); - loop { - if is_valid(&self.temp_input_audio_filename)? { - break; - } else if Instant::now().duration_since(start_time) >= duration { - return Err(Error::msg("Unable to validate tmp video file.")); - } - } - // If only audio is recording then convert it to chosen format - let mut ffmpeg_command = FfmpegCommand::new(); - ffmpeg_command.format("ogg"); - ffmpeg_command.input(&self.temp_input_audio_filename); - if is_output_audio_record(&self.temp_output_audio_filename) { - ffmpeg_command.input(&self.temp_output_audio_filename); - } - ffmpeg_command.args([ - "-c:a", - "aac", - &self.saved_filename - .clone() - ]).overwrite() - .spawn()? - .wait()?; - } else { - // Validate audio file integrity - let start_time = Instant::now(); - let duration = Duration::from_secs(60); - loop { - if is_valid(&self.temp_output_audio_filename)? { - break; - } else if Instant::now().duration_since(start_time) >= duration { - return Err(Error::msg("Unable to validate tmp video file.")); - } - } - // If only output audio is recording then convert it to chosen format - let mut ffmpeg_command = FfmpegCommand::new(); - ffmpeg_command.format("ogg"); - ffmpeg_command.input(&self.temp_output_audio_filename); - ffmpeg_command.arg(&self.saved_filename - .clone()) - .overwrite() - .spawn()? - .wait()?; } Ok(()) } // Clean tmp pub fn clean(&mut self) -> Result<()> { - let tmp_files = vec![ &self.temp_input_audio_filename, &self.temp_output_audio_filename, &self.temp_video_filename ]; - for file in tmp_files { - if Path::new(file).try_exists()? { - std::fs::remove_file(file)?; - } + if Path::new(&self.temp_video_filename).try_exists()? { + std::fs::remove_file(&self.temp_video_filename)?; } Ok(()) } diff --git a/core/src/lib.rs b/core/src/lib.rs index a9fd692..9cc61e2 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -1,7 +1,10 @@ -pub mod wayland_linux; - +#[cfg(any(target_os = "freebsd", target_os = "linux"))] pub mod ffmpeg_linux; +#[cfg(target_os = "windows")] pub mod ffmpeg_windows; -pub mod utils; \ No newline at end of file +pub mod utils; + +#[cfg(any(target_os = "freebsd", target_os = "linux"))] +pub mod wayland_linux; \ No newline at end of file diff --git a/gui/src/ui.rs b/gui/src/ui.rs index ff78c7f..3024dff 100644 --- a/gui/src/ui.rs +++ b/gui/src/ui.rs @@ -12,6 +12,7 @@ use blue_recorder_core::utils::{disable_input_widgets, enable_input_widgets, is_overwrite, is_wayland, play_record, RecordMode, validate_video_file}; #[cfg(any(target_os = "freebsd", target_os = "linux"))] use blue_recorder_core::utils::{audio_output_source, sources_descriptions_list}; +#[cfg(any(target_os = "freebsd", target_os = "linux"))] use blue_recorder_core::wayland_linux::WaylandRecorder; #[cfg(target_os = "windows")] use cpal::traits::{DeviceTrait, HostTrait}; @@ -275,12 +276,15 @@ fn build_ui(application: &Application, error_dialog: MessageDialog, error_messag video_switch.connect_toggled(move |switch: &CheckButton| { config_management::set_bool("default", "videocheck", switch.is_active()); if switch.is_active() { + #[cfg(any(target_os = "freebsd", target_os = "linux"))] _follow_mouse_switch.set_sensitive(true); _mouse_switch.set_sensitive(true); } else { _mouse_switch.set_active(false); _mouse_switch.set_sensitive(false); + #[cfg(any(target_os = "freebsd", target_os = "linux"))] _follow_mouse_switch.set_active(false); + #[cfg(any(target_os = "freebsd", target_os = "linux"))] _follow_mouse_switch.set_sensitive(false); } }); @@ -654,7 +658,7 @@ fn build_ui(application: &Application, error_dialog: MessageDialog, error_messag window_grab_button.set_tooltip_text(Some(&get_bundle("window-tooltip", None))); window_grab_label.set_label(&get_bundle("select-window", None)); #[cfg(target_os = "windows")] - let mut _window_title: Rc> = window_title.clone(); + let _window_title = window_title.clone(); window_grab_button.connect_clicked(move |_| { let text_buffer = TextBuffer::new(None); config_management::set_bool("default", "areacheck", _area_switch.is_active()); @@ -705,6 +709,7 @@ fn build_ui(application: &Application, error_dialog: MessageDialog, error_messag // Disable mouse cursor capture if video record is not active if !video_switch.is_active() { mouse_switch.set_sensitive(false); + #[cfg(any(target_os = "freebsd", target_os = "linux"))] follow_mouse_switch.set_sensitive(false); } @@ -751,15 +756,6 @@ fn build_ui(application: &Application, error_dialog: MessageDialog, error_messag } else { String::new() }; - let mode = if area_grab_button.is_active() { - RecordMode::Area - } else if window_grab_button.is_active() { - RecordMode::Window - } else { - RecordMode::Screen - }; - #[cfg(target_os = "windows")] - let window_title = window_title.borrow_mut().title.clone(); // Init record struct #[cfg(target_os = "windows")] @@ -772,10 +768,7 @@ fn build_ui(application: &Application, error_dialog: MessageDialog, error_messag format_chooser_combobox, ), output: String::new(), - temp_input_audio_filename: String::new(), - temp_output_audio_filename: String::new(), temp_video_filename: String::new(), - window_title, saved_filename: String::new(), height: None, input_audio_process: None, @@ -849,15 +842,25 @@ fn build_ui(application: &Application, error_dialog: MessageDialog, error_messag is_record_button_clicked: false, })); record_button.connect_clicked(move |_| { + let mode: RecordMode = if area_grab_button.is_active() { + RecordMode::Area + } else if window_grab_button.is_active() { + RecordMode::Window + } else { + RecordMode::Screen + }; + // Disable mouse cursor capture during record if _video_switch.is_active() { _mouse_switch.set_sensitive(false); + #[cfg(any(target_os = "freebsd", target_os = "linux"))] _follow_mouse_switch.set_sensitive(false); } match _ffmpeg_record_interface.borrow_mut().get_filename() { Err(error) => { if _video_switch.is_active() { _mouse_switch.set_sensitive(true); + #[cfg(any(target_os = "freebsd", target_os = "linux"))] _follow_mouse_switch.set_sensitive(true); } enable_input_widgets(_input_widgets.clone()); @@ -904,6 +907,8 @@ fn build_ui(application: &Application, error_dialog: MessageDialog, error_messag } } else if _delay_spin.value() as u16 == 0 { let _area_capture = area_capture.borrow_mut(); + #[cfg(target_os = "windows")] + let _window_title = window_title.borrow_mut(); disable_input_widgets(_input_widgets.clone()); start_timer(record_time_label.clone()); record_time_label.set_visible(true); @@ -921,6 +926,7 @@ fn build_ui(application: &Application, error_dialog: MessageDialog, error_messag Err(error) => { if _video_switch.is_active() { _mouse_switch.set_sensitive(true); + #[cfg(any(target_os = "freebsd", target_os = "linux"))] _follow_mouse_switch.set_sensitive(true); } enable_input_widgets(_input_widgets.clone()); @@ -941,6 +947,7 @@ fn build_ui(application: &Application, error_dialog: MessageDialog, error_messag Err(error) => { if _video_switch.is_active() { _mouse_switch.set_sensitive(true); + #[cfg(any(target_os = "freebsd", target_os = "linux"))] _follow_mouse_switch.set_sensitive(true); } enable_input_widgets(_input_widgets.clone()); @@ -954,19 +961,31 @@ fn build_ui(application: &Application, error_dialog: MessageDialog, error_messag } } if _video_switch.is_active() { - match _ffmpeg_record_interface.borrow_mut().start_video( + #[cfg(target_os = "windows")] + let start_video = _ffmpeg_record_interface.borrow_mut().start_video( + _area_capture.x, + _area_capture.y, + _area_capture.width, + _area_capture.height, + mode, + _window_title.title.clone(), + ); + #[cfg(any(target_os = "freebsd", target_os = "linux"))] + let start_video = _ffmpeg_record_interface.borrow_mut().start_video( _area_capture.x, _area_capture.y, _area_capture.width, _area_capture.height, mode - ) { + ); + match start_video { Ok(_) => { // Do nothing }, Err(error) => { if _video_switch.is_active() { _mouse_switch.set_sensitive(true); + #[cfg(any(target_os = "freebsd", target_os = "linux"))] _follow_mouse_switch.set_sensitive(true); } enable_input_widgets(_input_widgets.clone()); @@ -1012,6 +1031,7 @@ fn build_ui(application: &Application, error_dialog: MessageDialog, error_messag Err(error) => { if _video_switch.is_active() { _mouse_switch.set_sensitive(true); + #[cfg(any(target_os = "freebsd", target_os = "linux"))] _follow_mouse_switch.set_sensitive(true); } enable_input_widgets(input_widgets.clone()); @@ -1033,6 +1053,7 @@ fn build_ui(application: &Application, error_dialog: MessageDialog, error_messag Err(error) => { if _video_switch.is_active() { _mouse_switch.set_sensitive(true); + #[cfg(any(target_os = "freebsd", target_os = "linux"))] _follow_mouse_switch.set_sensitive(true); } enable_input_widgets(input_widgets.clone()); @@ -1054,6 +1075,7 @@ fn build_ui(application: &Application, error_dialog: MessageDialog, error_messag Err(error) => { if _video_switch.is_active() { _mouse_switch.set_sensitive(true); + #[cfg(any(target_os = "freebsd", target_os = "linux"))] _follow_mouse_switch.set_sensitive(true); } enable_input_widgets(input_widgets.clone()); @@ -1069,6 +1091,7 @@ fn build_ui(application: &Application, error_dialog: MessageDialog, error_messag } if _video_switch.is_active() { _mouse_switch.set_sensitive(true); + #[cfg(any(target_os = "freebsd", target_os = "linux"))] _follow_mouse_switch.set_sensitive(true); } enable_input_widgets(input_widgets.clone());