mirror of
https://github.com/xlmnxp/blue-recorder.git
synced 2025-04-02 07:44:54 +03:00
update core
This commit is contained in:
parent
44587f55fe
commit
626e056a82
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -483,7 +483,6 @@ dependencies = [
|
||||
"anyhow",
|
||||
"async-std",
|
||||
"blue-recorder-core",
|
||||
"chrono",
|
||||
"cpal",
|
||||
"dark-light",
|
||||
"dirs",
|
||||
@ -503,6 +502,7 @@ name = "blue-recorder-core"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"chrono",
|
||||
"ffmpeg-sidecar",
|
||||
"glib 0.10.3",
|
||||
"libadwaita",
|
||||
|
@ -5,11 +5,12 @@ edition = "2021"
|
||||
|
||||
[features]
|
||||
cmd = []
|
||||
gtk = ["dep:adw", "dep:glib", "dep:subprocess"]
|
||||
gtk = ["adw", "chrono", "glib", "subprocess"]
|
||||
|
||||
[dependencies]
|
||||
adw = { version = "0.2.1", package = "libadwaita", features = ["gtk_v4_6"], optional = true }
|
||||
anyhow = "1.0.86"
|
||||
chrono = { version = "0.4.19", optional = true }
|
||||
ffmpeg-sidecar = "1.1.0"
|
||||
glib = { version = "0.10.3", optional = true }
|
||||
open = "5.1.4"
|
||||
|
@ -1,9 +1,12 @@
|
||||
use adw::gtk::{CheckButton, ComboBoxText, Entry, FileChooserNative, SpinButton};
|
||||
use adw::gtk::prelude::*;
|
||||
use anyhow::{anyhow, Error, Result};
|
||||
use chrono::Utc;
|
||||
use ffmpeg_sidecar::child::FfmpegChild;
|
||||
use ffmpeg_sidecar::command::FfmpegCommand;
|
||||
use tempfile;
|
||||
use std::{cell::RefCell, time::Instant};
|
||||
use std::path::Path;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::rc::Rc;
|
||||
use std::thread::sleep;
|
||||
use std::time::Duration;
|
||||
@ -36,24 +39,25 @@ pub struct Ffmpeg {
|
||||
#[cfg(feature = "gtk")]
|
||||
#[derive(Clone)]
|
||||
pub struct Ffmpeg {
|
||||
pub audio_input_id: String,
|
||||
pub audio_input_id: ComboBoxText,
|
||||
pub audio_output_id: String,
|
||||
pub filename: 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 saved_filename: String,
|
||||
pub height: Option<u16>,
|
||||
pub input_audio_process: Option<Rc<RefCell<FfmpegChild>>>,
|
||||
pub output_audio_process: Option<Rc<RefCell<FfmpegChild>>>,
|
||||
pub video_process: Option<Rc<RefCell<FfmpegChild>>>,
|
||||
pub audio_record_bitrate: u16,
|
||||
pub record_delay: u16,
|
||||
pub record_frames: u16,
|
||||
pub video_record_bitrate: u16,
|
||||
pub follow_mouse: bool,
|
||||
pub record_mouse: bool,
|
||||
pub show_area: bool,
|
||||
pub audio_record_bitrate: SpinButton,
|
||||
pub record_delay: SpinButton,
|
||||
pub record_frames: SpinButton,
|
||||
pub video_record_bitrate: SpinButton,
|
||||
pub follow_mouse: CheckButton,
|
||||
pub record_mouse: CheckButton,
|
||||
pub show_area: CheckButton,
|
||||
}
|
||||
|
||||
#[cfg(feature = "cmd")]
|
||||
@ -423,6 +427,30 @@ impl Ffmpeg {
|
||||
|
||||
#[cfg(feature = "gtk")]
|
||||
impl Ffmpeg {
|
||||
// Get file name
|
||||
pub fn get_filename(&mut self) -> Result<String> {
|
||||
self.saved_filename =
|
||||
self.filename
|
||||
.0
|
||||
.file()
|
||||
.ok_or_else(|| anyhow!("Unable to get GFile."))?
|
||||
.path()
|
||||
.ok_or_else(|| anyhow!("Failed to get path from GFile."))?
|
||||
.join(PathBuf::from(format!(
|
||||
"{}.{}",
|
||||
if self.filename.1.text().to_string().trim().eq("") {
|
||||
Utc::now().to_string().replace(" UTC", "").replace(' ', "-")
|
||||
} else {
|
||||
self.filename.1.text().to_string().trim().to_string()
|
||||
},
|
||||
self.filename.2.active_id().ok_or_else(|| anyhow!("Failed to get active_id column."))?
|
||||
)))
|
||||
.as_path()
|
||||
.display()
|
||||
.to_string();
|
||||
Ok(self.saved_filename.clone())
|
||||
}
|
||||
|
||||
// Start video recording
|
||||
pub fn start_video(&mut self, x: u16, y: u16, width: u16, height: u16, mode: RecordMode) -> Result<()> {
|
||||
let display = format!("{}+{},{}",
|
||||
@ -434,9 +462,14 @@ impl Ffmpeg {
|
||||
let mut ffmpeg_command = FfmpegCommand::new();
|
||||
let format = "x11grab";
|
||||
self.height = Some(height);
|
||||
let filename = self.saved_filename.clone();
|
||||
self.output = Path::new(&filename).extension()
|
||||
.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.is_empty()
|
||||
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"
|
||||
{
|
||||
@ -454,7 +487,7 @@ impl Ffmpeg {
|
||||
}
|
||||
|
||||
// Record video with specified width and hight
|
||||
if self.follow_mouse {
|
||||
if self.follow_mouse.is_active() {
|
||||
match mode {
|
||||
RecordMode::Screen => {
|
||||
let width = width as f32 * 0.95;
|
||||
@ -470,25 +503,25 @@ impl Ffmpeg {
|
||||
}
|
||||
|
||||
// Show grabbed area
|
||||
if self.show_area {
|
||||
if self.show_area.is_active() {
|
||||
ffmpeg_command.args(["-show_region", "1"]);
|
||||
}
|
||||
|
||||
// If show mouse switch is enabled, draw the mouse to video
|
||||
if self.record_mouse {
|
||||
if self.record_mouse.is_active() {
|
||||
ffmpeg_command.args(["-draw_mouse", "1"]);
|
||||
} else {
|
||||
ffmpeg_command.args(["-draw_mouse", "0"]);
|
||||
};
|
||||
|
||||
// Follow the mouse
|
||||
if self.follow_mouse {
|
||||
if self.follow_mouse.is_active() {
|
||||
ffmpeg_command.args(["-follow_mouse", "centered"]);
|
||||
}
|
||||
|
||||
// Disable frame rate if value is zero
|
||||
if self.record_frames > 0 {
|
||||
ffmpeg_command.args(["-framerate", &self.record_frames.to_string()]);
|
||||
if self.record_frames.value() as u16 > 0 {
|
||||
ffmpeg_command.args(["-framerate", &self.record_frames.value().to_string()]);
|
||||
}
|
||||
|
||||
// Video format && input
|
||||
@ -496,15 +529,16 @@ impl Ffmpeg {
|
||||
.input(display);
|
||||
|
||||
// Disable bitrate if value is zero
|
||||
if self.video_record_bitrate > 0 {
|
||||
if self.video_record_bitrate.value() as u16 > 0 {
|
||||
ffmpeg_command.args([
|
||||
"-b:v",
|
||||
&format!("{}K", self.video_record_bitrate),
|
||||
&format!("{}K", self.video_record_bitrate.value() as u16),
|
||||
]);
|
||||
}
|
||||
|
||||
// tmp file
|
||||
if self.audio_input_id.is_empty() &&
|
||||
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"
|
||||
{
|
||||
@ -515,22 +549,25 @@ impl Ffmpeg {
|
||||
ffmpeg_command.args(["-map_metadata", "-1"]);
|
||||
|
||||
// Output
|
||||
let saved_filename = self.saved_filename.clone();
|
||||
ffmpeg_command.args([
|
||||
{
|
||||
if !self.audio_input_id.is_empty()
|
||||
if !self.audio_input_id.active_id()
|
||||
.ok_or_else(|| anyhow!("Failed to get active audio input device ID."))?
|
||||
.to_string().is_empty()
|
||||
|| !self.audio_output_id.is_empty()
|
||||
|| self.output == "gif"
|
||||
{
|
||||
&self.temp_video_filename
|
||||
} else {
|
||||
&self.filename
|
||||
&saved_filename
|
||||
}
|
||||
},
|
||||
]);
|
||||
ffmpeg_command.overwrite();
|
||||
|
||||
// Sleep for delay
|
||||
sleep(Duration::from_secs(self.record_delay as u64));
|
||||
sleep(Duration::from_secs(self.record_delay.value() as u64));
|
||||
|
||||
// Start recording and return the process id
|
||||
self.video_process = Some(Rc::new(RefCell::new(ffmpeg_command.spawn()?)));
|
||||
@ -561,13 +598,15 @@ impl Ffmpeg {
|
||||
.to_string();
|
||||
let mut ffmpeg_command = FfmpegCommand::new();
|
||||
ffmpeg_command.format("pulse")
|
||||
.input(&self.audio_input_id)
|
||||
.input(&self.audio_input_id.active_id()
|
||||
.ok_or_else(|| anyhow!("Failed to get audio input ID."))?
|
||||
)
|
||||
.format("ogg");
|
||||
// Disable bitrate if value is zero
|
||||
if self.audio_record_bitrate > 0 {
|
||||
if self.audio_record_bitrate.value() as u16 > 0 {
|
||||
ffmpeg_command.args([
|
||||
"-b:a",
|
||||
&format!("{}K", self.audio_record_bitrate),
|
||||
&format!("{}K", self.audio_record_bitrate.value() as u16),
|
||||
]);
|
||||
}
|
||||
// Remove metadate
|
||||
@ -577,7 +616,7 @@ impl Ffmpeg {
|
||||
|
||||
// Sleep for delay
|
||||
if !is_video_record(&self.temp_video_filename) {
|
||||
sleep(Duration::from_secs(self.record_delay as u64));
|
||||
sleep(Duration::from_secs(self.record_delay.value() as u64));
|
||||
}
|
||||
|
||||
// Start recording and return the process id
|
||||
@ -594,7 +633,7 @@ impl Ffmpeg {
|
||||
.ok_or_else(|| anyhow!("Not exiting the input audio recording process successfully."))?
|
||||
.borrow_mut()
|
||||
.quit()?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -617,7 +656,7 @@ impl Ffmpeg {
|
||||
|
||||
// Sleep for delay
|
||||
if !is_video_record(&self.temp_video_filename) && !is_input_audio_record(&self.temp_input_audio_filename) {
|
||||
sleep(Duration::from_secs(self.record_delay as u64));
|
||||
sleep(Duration::from_secs(self.record_delay.value() as u64));
|
||||
}
|
||||
|
||||
// Start recording and return the process id
|
||||
@ -664,7 +703,7 @@ impl Ffmpeg {
|
||||
ffmpeg_command.args([
|
||||
"-c:a",
|
||||
"aac",
|
||||
&self.filename,
|
||||
&self.saved_filename.clone()
|
||||
]);
|
||||
ffmpeg_command.overwrite()
|
||||
.spawn()?
|
||||
@ -682,10 +721,13 @@ impl Ffmpeg {
|
||||
}
|
||||
// Convert MP4 to GIF
|
||||
let filter = format!("fps={},scale={}:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse",
|
||||
self.record_frames,self.height.ok_or_else
|
||||
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.filename);
|
||||
-loop 0 {} -y", &self.temp_video_filename,filter,
|
||||
&self.saved_filename
|
||||
.clone());
|
||||
std::process::Command::new("sh").arg("-c").arg(&ffmpeg_convert).output()?;
|
||||
}
|
||||
} else if is_input_audio_record(&self.temp_input_audio_filename) {
|
||||
@ -709,7 +751,8 @@ impl Ffmpeg {
|
||||
ffmpeg_command.args([
|
||||
"-c:a",
|
||||
"aac",
|
||||
&self.filename,
|
||||
&self.saved_filename
|
||||
.clone()
|
||||
]).overwrite()
|
||||
.spawn()?
|
||||
.wait()?;
|
||||
@ -728,7 +771,8 @@ impl Ffmpeg {
|
||||
let mut ffmpeg_command = FfmpegCommand::new();
|
||||
ffmpeg_command.format("ogg");
|
||||
ffmpeg_command.input(&self.temp_output_audio_filename);
|
||||
ffmpeg_command.arg(&self.filename)
|
||||
ffmpeg_command.arg(&self.saved_filename
|
||||
.clone())
|
||||
.overwrite()
|
||||
.spawn()?
|
||||
.wait()?;
|
||||
|
@ -1,9 +1,12 @@
|
||||
use adw::gtk::{CheckButton, ComboBoxText, Entry, FileChooserNative, SpinButton};
|
||||
use adw::gtk::prelude::*;
|
||||
use anyhow::{anyhow, Error, Result};
|
||||
use chrono::Utc;
|
||||
use ffmpeg_sidecar::child::FfmpegChild;
|
||||
use ffmpeg_sidecar::command::FfmpegCommand;
|
||||
use tempfile;
|
||||
use std::{cell::RefCell, time::Instant};
|
||||
use std::path::Path;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::rc::Rc;
|
||||
use std::thread::sleep;
|
||||
use std::time::Duration;
|
||||
@ -37,25 +40,26 @@ pub struct Ffmpeg {
|
||||
#[cfg(feature = "gtk")]
|
||||
#[derive(Clone)]
|
||||
pub struct Ffmpeg {
|
||||
pub audio_input_id: String,
|
||||
pub audio_input_id: ComboBoxText,
|
||||
pub audio_output_id: String,
|
||||
pub filename: 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<u16>,
|
||||
pub input_audio_process: Option<Rc<RefCell<FfmpegChild>>>,
|
||||
pub output_audio_process: Option<Rc<RefCell<FfmpegChild>>>,
|
||||
pub video_process: Option<Rc<RefCell<FfmpegChild>>>,
|
||||
pub audio_record_bitrate: u16,
|
||||
pub record_delay: u16,
|
||||
pub record_frames: u16,
|
||||
pub video_record_bitrate: u16,
|
||||
pub follow_mouse: bool,
|
||||
pub record_mouse: bool,
|
||||
pub show_area: bool,
|
||||
pub audio_record_bitrate: SpinButton,
|
||||
pub record_delay: SpinButton,
|
||||
pub record_frames: SpinButton,
|
||||
pub video_record_bitrate: SpinButton,
|
||||
pub follow_mouse: CheckButton,
|
||||
pub record_mouse: CheckButton,
|
||||
pub show_area: CheckButton,
|
||||
}
|
||||
|
||||
#[cfg(feature = "cmd")]
|
||||
@ -414,6 +418,30 @@ impl Ffmpeg {
|
||||
|
||||
#[cfg(feature = "gtk")]
|
||||
impl Ffmpeg {
|
||||
// Get file name
|
||||
pub fn get_filename(&mut self) -> Result<String> {
|
||||
self.saved_filename =
|
||||
self.filename
|
||||
.0
|
||||
.file()
|
||||
.ok_or_else(|| anyhow!("Unable to get GFile."))?
|
||||
.path()
|
||||
.ok_or_else(|| anyhow!("Failed to get path from GFile."))?
|
||||
.join(PathBuf::from(format!(
|
||||
"{}.{}",
|
||||
if self.filename.1.text().to_string().trim().eq("") {
|
||||
Utc::now().to_string().replace(" UTC", "").replace(' ', "-")
|
||||
} else {
|
||||
self.filename.1.text().to_string().trim().to_string()
|
||||
},
|
||||
self.filename.2.active_id().ok_or_else(|| anyhow!("Failed to get active_id column."))?
|
||||
)))
|
||||
.as_path()
|
||||
.display()
|
||||
.to_string();
|
||||
Ok(self.saved_filename.clone())
|
||||
}
|
||||
|
||||
// Start video recording
|
||||
pub fn start_video(&mut self, x: u16, y: u16, width: u16, height: u16, mode: RecordMode) -> Result<()> {
|
||||
let display = match mode {
|
||||
@ -425,7 +453,8 @@ impl Ffmpeg {
|
||||
let format = "gdigrab";
|
||||
|
||||
// Record video to tmp if audio record enabled
|
||||
if !self.audio_input_id.is_empty()
|
||||
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"
|
||||
{
|
||||
@ -445,20 +474,20 @@ impl Ffmpeg {
|
||||
ffmpeg_command.format(format);
|
||||
|
||||
// Show grabbed area
|
||||
if self.show_area {
|
||||
if self.show_area.is_active() {
|
||||
ffmpeg_command.args(["-show_region", "1"]);
|
||||
}
|
||||
|
||||
// if show mouse switch is enabled, draw the mouse to video
|
||||
if self.record_mouse {
|
||||
if self.record_mouse.is_active() {
|
||||
ffmpeg_command.args(["-draw_mouse", "1"]);
|
||||
} else {
|
||||
ffmpeg_command.args(["-draw_mouse", "0"]);
|
||||
};
|
||||
|
||||
// Disable frame rate if value is zero
|
||||
if self.record_frames > 0 {
|
||||
ffmpeg_command.args(["-framerate", &self.record_frames.to_string()]);
|
||||
if self.record_frames.value() as u16 > 0 {
|
||||
ffmpeg_command.args(["-framerate", &self.record_frames.value().to_string()]);
|
||||
}
|
||||
|
||||
// Record video with specified width and hight
|
||||
@ -473,15 +502,16 @@ impl Ffmpeg {
|
||||
ffmpeg_command.input(display);
|
||||
|
||||
// Disable bitrate if value is zero
|
||||
if self.video_record_bitrate > 0 {
|
||||
if self.video_record_bitrate.value() as u16 > 0 {
|
||||
ffmpeg_command.args([
|
||||
"-b:v",
|
||||
&format!("{}K", self.video_record_bitrate),
|
||||
&format!("{}K", self.video_record_bitrate.value().to_string()),
|
||||
]);
|
||||
}
|
||||
|
||||
// tmp file
|
||||
if self.audio_input_id.is_empty() &&
|
||||
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"
|
||||
{
|
||||
@ -492,22 +522,24 @@ impl Ffmpeg {
|
||||
ffmpeg_command.args(["-map_metadata", "-1"]);
|
||||
|
||||
// Output
|
||||
let saved_filename = self.saved_filename.clone();
|
||||
ffmpeg_command.args([
|
||||
{
|
||||
if !self.audio_input_id.is_empty()
|
||||
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"
|
||||
{
|
||||
&self.temp_video_filename
|
||||
} else {
|
||||
&self.filename
|
||||
&saved_filename
|
||||
}
|
||||
},
|
||||
]);
|
||||
ffmpeg_command.overwrite();
|
||||
|
||||
// Sleep for delay
|
||||
sleep(Duration::from_secs(self.record_delay as u64));
|
||||
sleep(Duration::from_secs(self.record_delay.value() as u64));
|
||||
|
||||
// Start recording and return the process id
|
||||
self.video_process = Some(Rc::new(RefCell::new(ffmpeg_command.spawn()?)));
|
||||
@ -541,10 +573,10 @@ impl Ffmpeg {
|
||||
.input(format!("audio={}", &self.audio_input_id))
|
||||
.format("ogg");
|
||||
// Disable bitrate if value is zero
|
||||
if self.audio_record_bitrate > 0 {
|
||||
if self.audio_record_bitrate.value() as u16 > 0 {
|
||||
ffmpeg_command.args([
|
||||
"-b:a",
|
||||
&format!("{}K", self.audio_record_bitrate),
|
||||
&format!("{}K", self.audio_record_bitrate.value() as u16),
|
||||
]);
|
||||
}
|
||||
// Remove metadate
|
||||
@ -554,7 +586,7 @@ impl Ffmpeg {
|
||||
|
||||
// Sleep for delay
|
||||
if !is_video_record(&self.temp_video_filename) {
|
||||
sleep(Duration::from_secs(self.record_delay as u64));
|
||||
sleep(Duration::from_secs(self.record_delay.value() as u64));
|
||||
}
|
||||
|
||||
// Start recording and return the process id
|
||||
@ -594,7 +626,7 @@ impl Ffmpeg {
|
||||
|
||||
// Sleep for delay
|
||||
if !is_video_record(&self.temp_video_filename) && !is_input_audio_record(&self.temp_input_audio_filename) {
|
||||
sleep(Duration::from_secs(self.record_delay as u64));
|
||||
sleep(Duration::from_secs(self.record_delay.value() as u64));
|
||||
}
|
||||
|
||||
// Start recording and return the process id
|
||||
@ -641,7 +673,8 @@ impl Ffmpeg {
|
||||
ffmpeg_command.args([
|
||||
"-c:a",
|
||||
"aac",
|
||||
&self.filename,
|
||||
&self.saved_filename
|
||||
.clone()
|
||||
]);
|
||||
ffmpeg_command.overwrite()
|
||||
.spawn()?
|
||||
@ -659,10 +692,13 @@ impl Ffmpeg {
|
||||
}
|
||||
// Convert MP4 to GIF
|
||||
let filter = format!("fps={},scale={}:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse",
|
||||
self.record_frames,self.height.ok_or_else
|
||||
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.filename);
|
||||
-loop 0 {} -y", &self.temp_video_filename,filter,
|
||||
&self.saved_filename
|
||||
.clone());
|
||||
std::process::Command::new("sh").arg("-c").arg(&ffmpeg_convert).output()?;
|
||||
}
|
||||
} else if is_input_audio_record(&self.temp_input_audio_filename) {
|
||||
@ -686,7 +722,8 @@ impl Ffmpeg {
|
||||
ffmpeg_command.args([
|
||||
"-c:a",
|
||||
"aac",
|
||||
&self.filename,
|
||||
&self.saved_filename
|
||||
.clone()
|
||||
]).overwrite()
|
||||
.spawn()?
|
||||
.wait()?;
|
||||
@ -705,7 +742,8 @@ impl Ffmpeg {
|
||||
let mut ffmpeg_command = FfmpegCommand::new();
|
||||
ffmpeg_command.format("ogg");
|
||||
ffmpeg_command.input(&self.temp_output_audio_filename);
|
||||
ffmpeg_command.arg(&self.filename)
|
||||
ffmpeg_command.arg(&self.saved_filename
|
||||
.clone())
|
||||
.overwrite()
|
||||
.spawn()?
|
||||
.wait()?;
|
||||
|
@ -7,7 +7,6 @@ edition = "2021"
|
||||
anyhow = "1.0.86"
|
||||
async-std = {version = "1.12.0", features = ["attributes"]}
|
||||
blue-recorder-core = { path = "../core", features = ["gtk"] }
|
||||
chrono = "0.4.19"
|
||||
cpal = "0.15.3"
|
||||
dark-light = "1.0.0"
|
||||
dirs = "4.0.0"
|
||||
|
274
gui/src/ui.rs
274
gui/src/ui.rs
@ -9,11 +9,10 @@ use blue_recorder_core::ffmpeg_linux::Ffmpeg;
|
||||
#[cfg(target_os = "windows")]
|
||||
use blue_recorder_core::ffmpeg_windows::Ffmpeg;
|
||||
use blue_recorder_core::utils::{is_wayland, play_record, RecordMode};
|
||||
use chrono::Utc;
|
||||
use cpal::traits::{DeviceTrait, HostTrait};
|
||||
use std::cell::RefCell;
|
||||
use std::ops::Add;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::path::Path;
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::{area_capture, config_management, fluent::get_bundle};
|
||||
@ -692,34 +691,11 @@ fn build_ui(application: &Application, error_dialog: MessageDialog, error_messag
|
||||
});
|
||||
|
||||
// Record struct values
|
||||
let audio_input_id = if audio_input_switch.is_active() {
|
||||
audio_source_combobox.active_id().unwrap().to_string()
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
let audio_output_id = if audio_output_switch.is_active() {
|
||||
output_device
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
let audio_record_bitrate = audio_bitrate_spin.value() as u16;
|
||||
let filename = folder_chooser_native
|
||||
.file()
|
||||
.unwrap()
|
||||
.path()
|
||||
.unwrap()
|
||||
.join(PathBuf::from(format!(
|
||||
"{}.{}",
|
||||
if filename_entry.text().to_string().trim().eq("") {
|
||||
Utc::now().to_string().replace(" UTC", "").replace(' ', "-")
|
||||
} else {
|
||||
filename_entry.text().to_string().trim().to_string()
|
||||
},
|
||||
format_chooser_combobox.active_id().unwrap()
|
||||
)))
|
||||
.as_path()
|
||||
.display().to_string();
|
||||
let follow_mouse = follow_mouse_switch.is_active();
|
||||
let mode = if area_grab_button.is_active() {
|
||||
RecordMode::Area
|
||||
} else if window_grab_button.is_active() {
|
||||
@ -727,58 +703,62 @@ fn build_ui(application: &Application, error_dialog: MessageDialog, error_messag
|
||||
} else {
|
||||
RecordMode::Screen
|
||||
};
|
||||
let output = Path::new(&filename).extension().unwrap().to_string_lossy().to_string();
|
||||
let record_delay = delay_spin.value() as u16;
|
||||
let record_frames = frames_spin.value() as u16;
|
||||
let record_mouse = mouse_switch.is_active();
|
||||
let show_area = area_switch.is_active();
|
||||
let video_record_bitrate = video_bitrate_spin.value() as u16;
|
||||
#[cfg(target_os = "windows")]
|
||||
let window_title = window_title.borrow_mut().title.clone();
|
||||
|
||||
// Init record struct
|
||||
#[cfg(target_os = "windows")]
|
||||
let ffmpeg_record_interface: Rc<RefCell<Ffmpeg>> = Rc::new(RefCell::new(Ffmpeg {
|
||||
audio_input_id,
|
||||
audio_input_id: audio_source_combobox.clone(),
|
||||
audio_output_id,
|
||||
filename,
|
||||
output,
|
||||
filename: (
|
||||
folder_chooser_native,
|
||||
filename_entry,
|
||||
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,
|
||||
output_audio_process: None,
|
||||
video_process: None,
|
||||
audio_record_bitrate,
|
||||
record_delay,
|
||||
record_frames,
|
||||
video_record_bitrate,
|
||||
follow_mouse,
|
||||
record_mouse,
|
||||
show_area,
|
||||
audio_record_bitrate: audio_bitrate_spin,
|
||||
record_delay: delay_spin,
|
||||
record_frames: frames_spin,
|
||||
video_record_bitrate: video_bitrate_spin,
|
||||
follow_mouse: follow_mouse_switch,
|
||||
record_mouse: mouse_switch,
|
||||
show_area: area_switch
|
||||
}));
|
||||
#[cfg(any(target_os = "freebsd", target_os = "linux"))]
|
||||
let ffmpeg_record_interface: Rc<RefCell<Ffmpeg>> = Rc::new(RefCell::new(Ffmpeg {
|
||||
audio_input_id,
|
||||
audio_input_id: audio_source_combobox.clone(),
|
||||
audio_output_id,
|
||||
filename,
|
||||
output,
|
||||
filename: (
|
||||
folder_chooser_native,
|
||||
filename_entry,
|
||||
format_chooser_combobox,
|
||||
),
|
||||
output: String::new(),
|
||||
temp_input_audio_filename: String::new(),
|
||||
temp_output_audio_filename: String::new(),
|
||||
temp_video_filename: String::new(),
|
||||
saved_filename: String::new(),
|
||||
height: None,
|
||||
input_audio_process: None,
|
||||
output_audio_process: None,
|
||||
video_process: None,
|
||||
audio_record_bitrate,
|
||||
record_delay,
|
||||
record_frames,
|
||||
video_record_bitrate,
|
||||
follow_mouse,
|
||||
record_mouse,
|
||||
show_area,
|
||||
audio_record_bitrate: audio_bitrate_spin,
|
||||
record_delay: delay_spin.clone(),
|
||||
record_frames: frames_spin,
|
||||
video_record_bitrate: video_bitrate_spin,
|
||||
follow_mouse: follow_mouse_switch,
|
||||
record_mouse: mouse_switch,
|
||||
show_area: area_switch
|
||||
}));
|
||||
|
||||
// Record button
|
||||
@ -804,97 +784,107 @@ fn build_ui(application: &Application, error_dialog: MessageDialog, error_messag
|
||||
//let wayland_record = main_context.block_on(WaylandRecorder::new());
|
||||
let mut _ffmpeg_record_interface = ffmpeg_record_interface.clone();
|
||||
record_button.connect_clicked(move |_| {
|
||||
if !_audio_input_switch.is_active() &&
|
||||
!_audio_output_switch.is_active() &&
|
||||
!_video_switch.is_active()
|
||||
{
|
||||
// Do nothing
|
||||
} else {
|
||||
_delay_window_button.set_active(false);
|
||||
if _delay_spin.value() as u16 > 0 {
|
||||
recording_delay(
|
||||
_delay_spin.clone(),
|
||||
_delay_spin.value() as u16,
|
||||
delay_window.clone(),
|
||||
_delay_window_button.clone(),
|
||||
delay_window_label.clone(),
|
||||
_record_button.clone(),
|
||||
);
|
||||
} else if _delay_spin.value() as u16 == 0 {
|
||||
let _area_capture = area_capture.borrow_mut();
|
||||
let start_video_record = _ffmpeg_record_interface.borrow_mut().start_video(
|
||||
_area_capture.x,
|
||||
_area_capture.y,
|
||||
_area_capture.width,
|
||||
_area_capture.height,
|
||||
mode,
|
||||
);
|
||||
_audio_input_switch.set_sensitive(false);
|
||||
_audio_output_switch.set_sensitive(false);
|
||||
_video_switch.set_sensitive(false);
|
||||
start_timer(record_time_label.clone());
|
||||
record_time_label.set_visible(true);
|
||||
if hide_switch.is_active() {
|
||||
_main_window.minimize();
|
||||
}
|
||||
_play_button.hide();
|
||||
_record_button.hide();
|
||||
_stop_button.show();
|
||||
if _audio_input_switch.is_active() {
|
||||
match _ffmpeg_record_interface.borrow_mut().start_input_audio() {
|
||||
Ok(_) => {
|
||||
// Do nothing
|
||||
},
|
||||
Err(error) => {
|
||||
_audio_input_switch.set_sensitive(true);
|
||||
_audio_output_switch.set_sensitive(true);
|
||||
_video_switch.set_sensitive(true);
|
||||
_record_button.show();
|
||||
_stop_button.hide();
|
||||
let text_buffer = TextBuffer::new(None);
|
||||
text_buffer.set_text(&format!("{}", error));
|
||||
_error_message.set_buffer(Some(&text_buffer));
|
||||
_error_dialog.show();
|
||||
},
|
||||
match _ffmpeg_record_interface.borrow_mut().get_filename() {
|
||||
Err(error) => {
|
||||
let text_buffer = TextBuffer::new(None);
|
||||
text_buffer.set_text(&format!("{}", error));
|
||||
_error_message.set_buffer(Some(&text_buffer));
|
||||
_error_dialog.show();
|
||||
},
|
||||
Ok(_) => {
|
||||
if !_audio_input_switch.is_active() &&
|
||||
!_audio_output_switch.is_active() &&
|
||||
!_video_switch.is_active()
|
||||
{
|
||||
// Do nothing
|
||||
} else {
|
||||
_delay_window_button.set_active(false);
|
||||
if _delay_spin.value() as u16 > 0 {
|
||||
recording_delay(
|
||||
_delay_spin.clone(),
|
||||
_delay_spin.value() as u16,
|
||||
delay_window.clone(),
|
||||
_delay_window_button.clone(),
|
||||
delay_window_label.clone(),
|
||||
_record_button.clone(),
|
||||
);
|
||||
} else if _delay_spin.value() as u16 == 0 {
|
||||
let _area_capture = area_capture.borrow_mut();
|
||||
let start_video_record = _ffmpeg_record_interface.borrow_mut().start_video(
|
||||
_area_capture.x,
|
||||
_area_capture.y,
|
||||
_area_capture.width,
|
||||
_area_capture.height,
|
||||
mode,
|
||||
);
|
||||
_audio_input_switch.set_sensitive(false);
|
||||
_audio_output_switch.set_sensitive(false);
|
||||
_video_switch.set_sensitive(false);
|
||||
start_timer(record_time_label.clone());
|
||||
record_time_label.set_visible(true);
|
||||
if hide_switch.is_active() {
|
||||
_main_window.minimize();
|
||||
}
|
||||
_play_button.hide();
|
||||
_record_button.hide();
|
||||
_stop_button.show();
|
||||
if _audio_input_switch.is_active() {
|
||||
match _ffmpeg_record_interface.borrow_mut().start_input_audio() {
|
||||
Ok(_) => {
|
||||
// Do nothing
|
||||
},
|
||||
Err(error) => {
|
||||
_audio_input_switch.set_sensitive(true);
|
||||
_audio_output_switch.set_sensitive(true);
|
||||
_video_switch.set_sensitive(true);
|
||||
_record_button.show();
|
||||
_stop_button.hide();
|
||||
let text_buffer = TextBuffer::new(None);
|
||||
text_buffer.set_text(&format!("{}", error));
|
||||
_error_message.set_buffer(Some(&text_buffer));
|
||||
_error_dialog.show();
|
||||
},
|
||||
}
|
||||
}
|
||||
if _audio_output_switch.is_active() {
|
||||
match _ffmpeg_record_interface.borrow_mut().start_output_audio() {
|
||||
Ok(_) => {
|
||||
// Do nothing
|
||||
},
|
||||
Err(error) => {
|
||||
_audio_input_switch.set_sensitive(true);
|
||||
_audio_output_switch.set_sensitive(true);
|
||||
_video_switch.set_sensitive(true);
|
||||
_record_button.show();
|
||||
_stop_button.hide();
|
||||
let text_buffer = TextBuffer::new(None);
|
||||
text_buffer.set_text(&format!("{}", error));
|
||||
_error_message.set_buffer(Some(&text_buffer));
|
||||
_error_dialog.show();
|
||||
},
|
||||
}
|
||||
}
|
||||
if _video_switch.is_active() {
|
||||
match start_video_record {
|
||||
Ok(_) => {
|
||||
// Do nothing
|
||||
},
|
||||
Err(error) => {
|
||||
_audio_input_switch.set_sensitive(true);
|
||||
_audio_output_switch.set_sensitive(true);
|
||||
_video_switch.set_sensitive(true);
|
||||
_record_button.show();
|
||||
_stop_button.hide();
|
||||
let text_buffer = TextBuffer::new(None);
|
||||
text_buffer.set_text(&format!("{}", error));
|
||||
_error_message.set_buffer(Some(&text_buffer));
|
||||
_error_dialog.show();
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if _audio_output_switch.is_active() {
|
||||
match _ffmpeg_record_interface.borrow_mut().start_output_audio() {
|
||||
Ok(_) => {
|
||||
// Do nothing
|
||||
},
|
||||
Err(error) => {
|
||||
_audio_input_switch.set_sensitive(true);
|
||||
_audio_output_switch.set_sensitive(true);
|
||||
_video_switch.set_sensitive(true);
|
||||
_record_button.show();
|
||||
_stop_button.hide();
|
||||
let text_buffer = TextBuffer::new(None);
|
||||
text_buffer.set_text(&format!("{}", error));
|
||||
_error_message.set_buffer(Some(&text_buffer));
|
||||
_error_dialog.show();
|
||||
},
|
||||
}
|
||||
}
|
||||
if _video_switch.is_active() {
|
||||
match start_video_record {
|
||||
Ok(_) => {
|
||||
// Do nothing
|
||||
},
|
||||
Err(error) => {
|
||||
_audio_input_switch.set_sensitive(true);
|
||||
_audio_output_switch.set_sensitive(true);
|
||||
_video_switch.set_sensitive(true);
|
||||
_record_button.show();
|
||||
_stop_button.hide();
|
||||
let text_buffer = TextBuffer::new(None);
|
||||
text_buffer.set_text(&format!("{}", error));
|
||||
_error_message.set_buffer(Some(&text_buffer));
|
||||
_error_dialog.show();
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
@ -971,7 +961,7 @@ fn build_ui(application: &Application, error_dialog: MessageDialog, error_messag
|
||||
_video_switch.set_sensitive(true);
|
||||
record_button.show();
|
||||
_stop_button.hide();
|
||||
let file_name = _ffmpeg_record_interface.borrow_mut().filename.clone();
|
||||
let file_name = _ffmpeg_record_interface.borrow_mut().saved_filename.clone();
|
||||
if Path::new(&file_name).try_exists().is_ok() {
|
||||
_play_button.show();
|
||||
_play_button.set_tooltip_text(Some(&get_bundle("play-tooltip", None)));
|
||||
@ -991,7 +981,7 @@ fn build_ui(application: &Application, error_dialog: MessageDialog, error_messag
|
||||
let _error_message = error_message.clone();
|
||||
let mut _ffmpeg_record_interface = ffmpeg_record_interface.clone();
|
||||
play_button.connect_clicked(move |_| {
|
||||
let file_name = _ffmpeg_record_interface.borrow_mut().filename.clone();
|
||||
let file_name = _ffmpeg_record_interface.borrow_mut().saved_filename.clone();
|
||||
match play_record(&file_name) {
|
||||
Ok(_) => {
|
||||
// Do nothing
|
||||
|
Loading…
Reference in New Issue
Block a user