diff --git a/src/config_management.rs b/src/config_management.rs index 4370abb..b27d6f8 100644 --- a/src/config_management.rs +++ b/src/config_management.rs @@ -25,24 +25,8 @@ pub fn initialize() -> PathBuf { config_path } -fn merge_previous_version() -> Option { - let config_path: PathBuf = Path::new(&get_user_data_dir().unwrap()) - .join("blue-recorder") - .join("config.ini"); - - // return none if config.ini not exists - if !&config_path.exists() { - return None; - } - - let mut config_string: String = String::from_utf8(std::fs::read(&config_path).unwrap()).unwrap(); - config_string = config_string.replace("Options", "default").replace("True", "1").replace("False", "0"); - std::fs::write(&config_path, config_string).unwrap(); - Some(config_path) -} - fn default() { - set("default", "frame", "50"); + set("default", "frame", "60"); set("default", "delay", "0"); set( "default", @@ -64,6 +48,22 @@ fn default() { set("default", "followmousecheck", "0"); } +fn merge_previous_version() -> Option { + let config_path: PathBuf = Path::new(&get_user_data_dir().unwrap()) + .join("blue-recorder") + .join("config.ini"); + + // return none if config.ini not exists + if !&config_path.exists() { + return None; + } + + let mut config_string: String = String::from_utf8(std::fs::read(&config_path).unwrap()).unwrap(); + config_string = config_string.replace("Options", "default").replace("True", "1").replace("False", "0"); + std::fs::write(&config_path, config_string).unwrap(); + Some(config_path) +} + pub fn get(selection: &str, key: &str) -> String { let config_path: PathBuf = Path::new(&get_user_data_dir().unwrap()) .join("blue-recorder") diff --git a/src/ffmpeg_interface.rs b/src/ffmpeg_interface.rs new file mode 100644 index 0000000..ba4bb89 --- /dev/null +++ b/src/ffmpeg_interface.rs @@ -0,0 +1,66 @@ +use std::path::PathBuf; +use std::process::Command; +use std::time::Duration; +use std::thread::sleep; + +pub struct Ffmpeg { + pub filename: PathBuf, + pub record_video: bool, + pub record_audio: bool, + pub audio_id: String, + pub record_mouse: bool, + pub follow_mouse: bool, + pub record_frames: String, + pub record_delay: u64, +} +impl Ffmpeg { + pub fn record(self, x: i16, y: i16, width: i16, height: i16) -> u32 { + let mut ffmpeg_command: Command = Command::new("ffmpeg"); + + // if recorder video switch is enabled, record video with specified width and hight + if self.record_video { + ffmpeg_command.arg("-video_size"); + ffmpeg_command.arg(format!("{}x{}", width, height)); + } + + // if show mouse switch is enabled, draw the mouse to video + if self.record_mouse { + ffmpeg_command.arg("-draw_mouse"); + ffmpeg_command.arg("1"); + } + + // if follow mouse switch is enabled, follow the mouse + if self.follow_mouse { + ffmpeg_command.arg("-follow_mouse"); + ffmpeg_command.arg("centered"); + } + + ffmpeg_command.arg("-framerate"); + ffmpeg_command.arg(self.record_frames); + ffmpeg_command.arg("-f"); + ffmpeg_command.arg("x11grab"); + ffmpeg_command.arg("-i"); + ffmpeg_command.arg(format!("{}+{},{}", std::env::var("DISPLAY").expect(":1").as_str(), x, y)); + + // if follow audio switch is enabled, record the audio + if self.record_audio { + ffmpeg_command.arg("-f"); + ffmpeg_command.arg("pulse"); + ffmpeg_command.arg("-i"); + ffmpeg_command.arg(self.audio_id); + ffmpeg_command.arg("-strict"); + ffmpeg_command.arg("-2"); + } + + ffmpeg_command.arg("-q"); + ffmpeg_command.arg("1"); + ffmpeg_command.arg(self.filename); + ffmpeg_command.arg("-y"); + + // sleep for delay + sleep(Duration::new(self.record_delay, 0)); + + // start recording and return the process id + ffmpeg_command.spawn().unwrap().id() + } +} diff --git a/src/main.rs b/src/main.rs index 278355a..3acb663 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,6 +2,7 @@ extern crate gdk; extern crate gio; extern crate gtk; mod config_management; +mod ffmpeg_interface; // use gio::prelude::*; use glib::signal::Inhibit; @@ -11,7 +12,7 @@ use gtk::{ AboutDialog, Adjustment, Builder, Button, CheckButton, CssProvider, Entry, FileChooser, Label, MenuItem, SpinButton, Window, }; -use std::path::Path; +use std::path::{Path,PathBuf}; use std::process::{Command, Stdio}; fn main() { @@ -43,9 +44,6 @@ fn main() { let frames_spin: SpinButton = builder.get_object("frames").unwrap(); let delay_spin: SpinButton = builder.get_object("delay").unwrap(); let audio_source_label: Label = builder.get_object("audio_source_label").unwrap(); - let delay_adjustment: Adjustment = builder.get_object("adjustment1").unwrap(); - let frames_adjustment: Adjustment = builder.get_object("adjustment2").unwrap(); - let delay_pref_adjustment: Adjustment = builder.get_object("adjustment3").unwrap(); let video_switch: CheckButton = builder.get_object("videoswitch").unwrap(); let audio_switch: CheckButton = builder.get_object("audioswitch").unwrap(); let mouse_switch: CheckButton = builder.get_object("mouseswitch").unwrap(); @@ -72,7 +70,8 @@ fn main() { format_chooser_combobox.append(Some("avi"), "AVI (Audio Video Interleaved)"); format_chooser_combobox.append(Some("mp4"), "MP4 (MPEG-4 Part 14)"); format_chooser_combobox.append(Some("wmv"), "WMV (Windows Media Video)"); - format_chooser_combobox.append(Some("gif"), "GIF (Graphics Interchange Format)"); + // TODO: gif not work at this time, fix it! + // format_chooser_combobox.append(Some("gif"), "GIF (Graphics Interchange Format)"); format_chooser_combobox.append(Some("nut"), "NUT (NUT Recording Format)"); format_chooser_combobox.set_active(Some(0)); @@ -214,6 +213,20 @@ fn main() { _area_chooser_window.show(); }); + record_button.connect_clicked(move |_| { + let record_options = ffmpeg_interface::Ffmpeg { + filename: folder_chooser.get_filename().unwrap().join(PathBuf::from(format!("{}.{}", if filename_entry.get_text().to_string().trim().eq("") { filename_entry.get_text().to_string() } else { filename_entry.get_text().to_string().trim().to_string() }, format_chooser_combobox.get_active_id().unwrap().to_string()))), + record_video: video_switch.get_active(), + record_audio: audio_switch.get_active(), + audio_id: audio_source_combobox.get_active_id().unwrap().to_string(), + record_mouse: mouse_switch.get_active(), + follow_mouse: follow_mouse_switch.get_active(), + record_frames: format!("{}", frames_spin.get_value()), + record_delay: delay_spin.get_value() as u64 + }; + record_options.record(0, 0, 512, 512); + }); + // Windows // hide area chooser after it deleted. let _area_chooser_window = area_chooser_window.to_owned();