diff --git a/Cargo.lock b/Cargo.lock index a3d1502..53fffd7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -77,6 +77,7 @@ dependencies = [ "gtk4", "regex", "rust-ini", + "secfmt", "subprocess", ] @@ -102,7 +103,7 @@ dependencies = [ [[package]] name = "cairo-rs" version = "0.17.0" -source = "git+https://github.com/gtk-rs/gtk-rs-core#4f5e597590e30183c819c9cf15f74bd87e9ac687" +source = "git+https://github.com/gtk-rs/gtk-rs-core#cc7a2b1de10b1bc65f1841f259b8c118fec4221c" dependencies = [ "bitflags", "cairo-sys-rs 0.17.0", @@ -126,7 +127,7 @@ dependencies = [ [[package]] name = "cairo-sys-rs" version = "0.17.0" -source = "git+https://github.com/gtk-rs/gtk-rs-core#4f5e597590e30183c819c9cf15f74bd87e9ac687" +source = "git+https://github.com/gtk-rs/gtk-rs-core#cc7a2b1de10b1bc65f1841f259b8c118fec4221c" dependencies = [ "glib-sys 0.17.0", "libc", @@ -400,7 +401,7 @@ dependencies = [ [[package]] name = "gdk-pixbuf" version = "0.17.0" -source = "git+https://github.com/gtk-rs/gtk-rs-core#4f5e597590e30183c819c9cf15f74bd87e9ac687" +source = "git+https://github.com/gtk-rs/gtk-rs-core#cc7a2b1de10b1bc65f1841f259b8c118fec4221c" dependencies = [ "bitflags", "gdk-pixbuf-sys 0.17.0", @@ -438,7 +439,7 @@ dependencies = [ [[package]] name = "gdk-pixbuf-sys" version = "0.17.0" -source = "git+https://github.com/gtk-rs/gtk-rs-core#4f5e597590e30183c819c9cf15f74bd87e9ac687" +source = "git+https://github.com/gtk-rs/gtk-rs-core#cc7a2b1de10b1bc65f1841f259b8c118fec4221c" dependencies = [ "gio-sys 0.17.0", "glib-sys 0.17.0", @@ -483,7 +484,7 @@ dependencies = [ [[package]] name = "gdk4" version = "0.6.0" -source = "git+https://github.com/gtk-rs/gtk4-rs.git#dd4d418dfe8872bacfe210b34b683530548b5d63" +source = "git+https://github.com/gtk-rs/gtk4-rs.git#e47eca402b90322ec9e8c2fcc0f93d6a3a8b037e" dependencies = [ "bitflags", "cairo-rs 0.17.0", @@ -515,7 +516,7 @@ dependencies = [ [[package]] name = "gdk4-sys" version = "0.6.0" -source = "git+https://github.com/gtk-rs/gtk4-rs.git#dd4d418dfe8872bacfe210b34b683530548b5d63" +source = "git+https://github.com/gtk-rs/gtk4-rs.git#e47eca402b90322ec9e8c2fcc0f93d6a3a8b037e" dependencies = [ "cairo-sys-rs 0.17.0", "gdk-pixbuf-sys 0.17.0", @@ -600,7 +601,7 @@ dependencies = [ [[package]] name = "gio" version = "0.17.0" -source = "git+https://github.com/gtk-rs/gtk-rs-core#4f5e597590e30183c819c9cf15f74bd87e9ac687" +source = "git+https://github.com/gtk-rs/gtk-rs-core#cc7a2b1de10b1bc65f1841f259b8c118fec4221c" dependencies = [ "bitflags", "futures-channel", @@ -645,7 +646,7 @@ dependencies = [ [[package]] name = "gio-sys" version = "0.17.0" -source = "git+https://github.com/gtk-rs/gtk-rs-core#4f5e597590e30183c819c9cf15f74bd87e9ac687" +source = "git+https://github.com/gtk-rs/gtk-rs-core#cc7a2b1de10b1bc65f1841f259b8c118fec4221c" dependencies = [ "glib-sys 0.17.0", "gobject-sys 0.17.0", @@ -696,7 +697,7 @@ dependencies = [ [[package]] name = "glib" version = "0.17.0" -source = "git+https://github.com/gtk-rs/gtk-rs-core#4f5e597590e30183c819c9cf15f74bd87e9ac687" +source = "git+https://github.com/gtk-rs/gtk-rs-core#cc7a2b1de10b1bc65f1841f259b8c118fec4221c" dependencies = [ "bitflags", "futures-channel", @@ -748,7 +749,7 @@ dependencies = [ [[package]] name = "glib-macros" version = "0.17.0" -source = "git+https://github.com/gtk-rs/gtk-rs-core#4f5e597590e30183c819c9cf15f74bd87e9ac687" +source = "git+https://github.com/gtk-rs/gtk-rs-core#cc7a2b1de10b1bc65f1841f259b8c118fec4221c" dependencies = [ "anyhow", "heck 0.4.0", @@ -782,7 +783,7 @@ dependencies = [ [[package]] name = "glib-sys" version = "0.17.0" -source = "git+https://github.com/gtk-rs/gtk-rs-core#4f5e597590e30183c819c9cf15f74bd87e9ac687" +source = "git+https://github.com/gtk-rs/gtk-rs-core#cc7a2b1de10b1bc65f1841f259b8c118fec4221c" dependencies = [ "libc", "system-deps 6.0.3", @@ -813,7 +814,7 @@ dependencies = [ [[package]] name = "gobject-sys" version = "0.17.0" -source = "git+https://github.com/gtk-rs/gtk-rs-core#4f5e597590e30183c819c9cf15f74bd87e9ac687" +source = "git+https://github.com/gtk-rs/gtk-rs-core#cc7a2b1de10b1bc65f1841f259b8c118fec4221c" dependencies = [ "glib-sys 0.17.0", "libc", @@ -1024,9 +1025,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.135" +version = "0.2.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c" +checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89" [[package]] name = "link-cplusplus" @@ -1163,7 +1164,7 @@ dependencies = [ [[package]] name = "pango" version = "0.17.0" -source = "git+https://github.com/gtk-rs/gtk-rs-core#4f5e597590e30183c819c9cf15f74bd87e9ac687" +source = "git+https://github.com/gtk-rs/gtk-rs-core#cc7a2b1de10b1bc65f1841f259b8c118fec4221c" dependencies = [ "bitflags", "gio 0.17.0", @@ -1188,7 +1189,7 @@ dependencies = [ [[package]] name = "pango-sys" version = "0.17.0" -source = "git+https://github.com/gtk-rs/gtk-rs-core#4f5e597590e30183c819c9cf15f74bd87e9ac687" +source = "git+https://github.com/gtk-rs/gtk-rs-core#cc7a2b1de10b1bc65f1841f259b8c118fec4221c" dependencies = [ "glib-sys 0.17.0", "gobject-sys 0.17.0", @@ -1220,9 +1221,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" +checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" [[package]] name = "ppv-lite86" @@ -1393,6 +1394,12 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8132065adcfd6e02db789d9285a0deb2f3fcb04002865ab67d5fb103533898" +[[package]] +name = "secfmt" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8c73432861711997c5d0a1f61275cb4e875884c820da5ff2cffad3d3577201c" + [[package]] name = "semver" version = "0.11.0" diff --git a/Cargo.toml b/Cargo.toml index 42c9c26..c0a228e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,7 @@ gtk-sys = "0.15" glib = "0.10.3" rust-ini = "0.16" regex = "1.4.3" +secfmt = "0.1.1" subprocess = "0.2.6" [dependencies.gio] diff --git a/interfaces/main.ui b/interfaces/main.ui index 8a06101..1be6b15 100644 --- a/interfaces/main.ui +++ b/interfaces/main.ui @@ -103,6 +103,48 @@ + + True + main_window + False + True + 200 + 200 + False + False + + + vertical + + + delay_window_title + True + Start Recording in… + 10 + + + + + delay_window_label + True + True + True + + + + + True + True + True + 10 + 10 + 10 + Stop + + + + + True True diff --git a/src/ffmpeg_interface.rs b/src/ffmpeg_interface.rs index 53333c7..07c6bba 100644 --- a/src/ffmpeg_interface.rs +++ b/src/ffmpeg_interface.rs @@ -1,4 +1,5 @@ extern crate subprocess; + use chrono::prelude::*; use gettextrs::gettext; use gtk::prelude::*; @@ -53,7 +54,6 @@ pub struct Ffmpeg { pub record_mouse: CheckButton, pub follow_mouse: CheckButton, pub record_frames: SpinButton, - pub record_delay: SpinButton, pub command: Entry, pub video_process_id: Option, pub audio_process_id: Option, @@ -169,8 +169,6 @@ impl Ffmpeg { ffmpeg_command.arg("1"); ffmpeg_command.arg(self.saved_filename.as_ref().unwrap()); ffmpeg_command.arg("-y"); - // Sleep for delay - sleep(Duration::from_secs(self.record_delay.value() as u64)); // Start recording and return the process id self.video_process_id = Some(ffmpeg_command.spawn().unwrap().id()); return (self.video_process_id, self.audio_process_id); diff --git a/src/main.rs b/src/main.rs index 2147b9e..5a9daf4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,19 +5,22 @@ extern crate gtk; mod area_capture; mod config_management; mod ffmpeg_interface; +mod timer; use ffmpeg_interface::{Ffmpeg, ProgressWidget}; use gettextrs::{bindtextdomain, gettext, LocaleCategory, setlocale, textdomain}; -use gtk::{prelude::*, Application}; -use gtk::{AboutDialog, Builder, Button, CheckButton, ComboBoxText, CssProvider, Entry, FileChooserNative, FileChooserAction, Image, Label, MessageDialog, ProgressBar, SpinButton, ToggleButton, Window}; +use gtk::{AboutDialog, Application, Builder, Button, CheckButton, ComboBoxText, CssProvider, Entry, FileChooserNative, FileChooserAction, Image, Label, MessageDialog, ProgressBar, SpinButton, ToggleButton, Window}; +use gtk::prelude::*; +use gtk::glib; use std::cell::RefCell; use std::ops::Add; use std::path::Path; use std::process::{Command, Stdio}; use std::rc::Rc; +use timer::{recording_delay}; fn main() { - //Create new application + // Create new application let application = Application::new(Some("sa.sy.blue-recorder"), Default::default(),); application.connect_activate(build_ui); application.run(); @@ -70,6 +73,9 @@ pub fn build_ui(application: &Application) { let command_label: Label = builder.object("command_label").unwrap(); let delay_label: Label = builder.object("delay_label").unwrap(); let delay_spin: SpinButton = builder.object("delay").unwrap(); + let delay_window: Window = builder.object("delay_window").unwrap(); + let delay_window_label: Label = builder.object("delay_window_label").unwrap(); + let delay_window_button: Button = builder.object("delay_window_stopbutton").unwrap(); let filename_entry: Entry = builder.object("filename").unwrap(); let folder_chooser_button: Button = builder.object("folder_chooser").unwrap(); let folder_chooser_image: Image = builder.object("folder_chooser_image").unwrap(); @@ -96,13 +102,13 @@ pub fn build_ui(application: &Application) { // Windows main_window.set_title(Some(&gettext("Blue Recorder"))); main_window.set_application(Some(application)); - area_chooser_window.set_title(Some(&gettext("Area Chooser"))); //title is hidden + area_chooser_window.set_title(Some(&gettext("Area Chooser"))); // Title is hidden - //Hide stop & play buttons + // Hide stop & play buttons stop_button.hide(); play_button.hide(); - //Hide window grab button in Wayland + // Hide window grab button in Wayland if is_wayland() { window_grab_button.hide(); } @@ -276,6 +282,18 @@ pub fn build_ui(application: &Application) { audio_source_label.set_label(&gettext("Audio Input Source:")); // Spin + frames_spin.set_value( + config_management::get("default", "frame") + .parse::() + .unwrap(), + ); + + delay_spin.set_value( + config_management::get("default", "delay") + .parse::() + .unwrap(), + ); + let _frames_spin = frames_spin.to_owned(); frames_spin.connect_value_changed(move |_| { config_management::set( @@ -375,7 +393,6 @@ pub fn build_ui(application: &Application) { record_mouse: mouse_switch, follow_mouse: follow_mouse_switch, record_frames: frames_spin, - record_delay: delay_spin, command: command_entry, video_process_id: None, audio_process_id: None, @@ -386,30 +403,39 @@ pub fn build_ui(application: &Application) { overwrite: overwrite_switch, })); + let _delay_window = delay_window.clone(); let mut _ffmpeg_record_interface = ffmpeg_record_interface.clone(); - let _stop_button = stop_button.clone(); let _record_button = record_button.clone(); + let _stop_button = stop_button.clone(); record_button.connect_clicked(move |_| { - let _area_capture = area_capture.borrow_mut(); - match _ffmpeg_record_interface.borrow_mut().start_record( - _area_capture.x, - _area_capture.y, - _area_capture.width, - _area_capture.height, - ) { - (None, None) => { + if delay_spin.value()as u64 > 0 { + recording_delay(delay_spin.clone(), delay_spin.value()as u64, delay_window.clone(), delay_window_label.clone(), _record_button.clone()); + } + if delay_spin.value()as u64 == 0 { + let _area_capture = area_capture.borrow_mut(); + match _ffmpeg_record_interface.borrow_mut().start_record( + _area_capture.x, + _area_capture.y, + _area_capture.width, + _area_capture.height, + ) { + (None, None) => { // Do nothing if the start_record function return nothing } - _ => { - _record_button.hide(); - _stop_button.show(); + _ => { + _record_button.hide(); + _stop_button.show(); + } } } }); + delay_window_button.connect_clicked(move |_| { + }); + let mut _ffmpeg_record_interface = ffmpeg_record_interface.clone(); - let _stop_button = stop_button.clone(); let _play_button = play_button.clone(); + let _stop_button = stop_button.clone(); stop_button.connect_clicked(move |_| { _ffmpeg_record_interface.borrow_mut().clone().stop_record(); record_button.show(); diff --git a/src/styles/global.css b/src/styles/global.css index e4bd359..a3177b6 100644 --- a/src/styles/global.css +++ b/src/styles/global.css @@ -22,3 +22,13 @@ color: @theme_selected_fg_color; background: @theme_selected_bg_color; } + +#delay_window_label{ + font-size: 350%; + font-weight: 250; +} + +#delay_window_title{ + font-size: 120%; + font-weight: 50; +} diff --git a/src/timer.rs b/src/timer.rs index e6d2789..f25000d 100644 --- a/src/timer.rs +++ b/src/timer.rs @@ -1 +1,34 @@ -// TODO: add timer +extern crate secfmt; + +use gtk::glib; +use gtk::{Button, Label, SpinButton, Window}; +use gtk::prelude::*; + +pub fn recording_delay(delay_spin: SpinButton, mut delay_time: u64, delay_window: Window, delay_window_label: Label, record_button: Button) { + // Keep time label alive and update every 1sec + let default_value = delay_time; + let capture_label = move || { + // Show delay window if delay time is not zero + delay_window.show(); + if delay_time > 0 { + delay_window_label.set_text(¤t_time(delay_time)); + delay_time -= 1; + glib::source::Continue(true) + } else { + // Hide delay window and start recording + delay_window.hide(); + delay_spin.set_value(0.0); + record_button.emit_clicked(); + // Keep the input value + delay_spin.set_value(default_value as f64); + glib::source::Continue(false) + } + }; + // Execute capture_label every 1sec + glib::source::timeout_add_seconds_local(1, capture_label); +} + +fn current_time(delay_time: u64) -> String { + let delay = secfmt::from(delay_time); + format!("{}:{}", delay.minutes, delay.seconds) +}