mirror of
https://github.com/xlmnxp/blue-recorder.git
synced 2024-11-23 17:13:11 +03:00
remove wayland from ffmpeg-interface
This commit is contained in:
parent
8092950cb6
commit
835e4660da
757
Cargo.lock
generated
757
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "blue-recorder"
|
||||
version = "0.1.0"
|
||||
version = "0.2.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
@ -14,12 +14,9 @@ gettext-rs = "0.7.0"
|
||||
gtk = { version = "0.4.8", package = "gtk4" }
|
||||
gtk-sys = "0.15"
|
||||
glib = "0.10.3"
|
||||
libappindicator = "0.5.2"
|
||||
rust-ini = "0.16"
|
||||
regex = "1.4.3"
|
||||
subprocess = "0.2.6"
|
||||
zbus = "1.9.2"
|
||||
zvariant = "2.10.0"
|
||||
|
||||
[dependencies.gio]
|
||||
version = "0.15.0"
|
||||
|
4
data/screenshot-ui-area-symbolic.svg
Normal file
4
data/screenshot-ui-area-symbolic.svg
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg height="32px" viewBox="0 0 32 32" width="32px" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m 3.5 2 c -1.929688 0.007812 -3.4921875 1.570312 -3.5 3.5 c 0 1.386719 0.820312 2.59375 2 3.15625 v 3.34375 h 2 v -3.035156 c 1.53125 -0.230469 2.734375 -1.433594 2.964844 -2.964844 h 2.035156 v -2 h -2.34375 c -0.578125 -1.21875 -1.808594 -1.996094 -3.15625 -2 z m 25 0 c -1.347656 0.003906 -2.578125 0.78125 -3.15625 2 h -2.34375 v 2 h 2.035156 c 0.230469 1.53125 1.433594 2.734375 2.964844 2.964844 v 3.035156 h 2 v -3.34375 c 1.21875 -0.578125 1.996094 -1.808594 2 -3.15625 c 0 -1.921875 -1.578125 -3.5 -3.5 -3.5 z m -25 2 c 0.839844 0 1.5 0.660156 1.5 1.5 s -0.660156 1.5 -1.5 1.5 s -1.5 -0.660156 -1.5 -1.5 s 0.660156 -1.5 1.5 -1.5 z m 7.5 0 v 2 h 4 v -2 z m 6 0 v 2 h 4 v -2 z m 11.5 0 c 0.839844 0 1.5 0.660156 1.5 1.5 s -0.660156 1.5 -1.5 1.5 s -1.5 -0.660156 -1.5 -1.5 s 0.660156 -1.5 1.5 -1.5 z m -26.5 10 v 4 h 2 v -4 z m 26 0 v 4 h 2 v -4 z m -26 6 v 3.34375 c -1.21875 0.578125 -1.99609375 1.808594 -2 3.15625 c 0 1.921875 1.578125 3.5 3.5 3.5 c 1.347656 -0.003906 2.578125 -0.78125 3.15625 -2 h 2.34375 v -2 h -2.035156 c -0.230469 -1.53125 -1.433594 -2.734375 -2.964844 -2.964844 v -3.035156 z m 26 0 v 3.035156 c -1.53125 0.230469 -2.734375 1.433594 -2.964844 2.964844 h -2.035156 v 2 h 2.34375 c 0.578125 1.21875 1.808594 1.996094 3.15625 2 c 1.921875 0 3.5 -1.578125 3.5 -3.5 c -0.003906 -1.347656 -0.78125 -2.578125 -2 -3.15625 v -3.34375 z m -24.5 5 c 0.839844 0 1.5 0.660156 1.5 1.5 s -0.660156 1.5 -1.5 1.5 s -1.5 -0.660156 -1.5 -1.5 s 0.660156 -1.5 1.5 -1.5 z m 25 0 c 0.839844 0 1.5 0.660156 1.5 1.5 s -0.660156 1.5 -1.5 1.5 s -1.5 -0.660156 -1.5 -1.5 s 0.660156 -1.5 1.5 -1.5 z m -17.5 1 v 2 h 4 v -2 z m 6 0 v 2 h 4 v -2 z m 0 0" fill="#241f31"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.8 KiB |
4
data/screenshot-ui-display-symbolic.svg
Normal file
4
data/screenshot-ui-display-symbolic.svg
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg height="32px" viewBox="0 0 32 32" width="32px" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m 4 4 c -1.660156 0 -3 1.339844 -3 3 v 14 c 0 1.660156 1.339844 3 3 3 h 10 v 3 h -3 c -1.09375 -0.003906 -2 0.90625 -2 2 h 14 c 0 -1.09375 -0.910156 -2 -2 -2 h -3 v -3 h 10 c 1.660156 0 3 -1.339844 3 -3 v -14 c 0 -1.660156 -1.339844 -3 -3 -3 z m 0 2 h 24 c 0.554688 0 1 0.445312 1 1 v 14 c 0 0.554688 -0.445312 1 -1 1 h -24 c -0.554688 0 -1 -0.445312 -1 -1 v -14 c 0 -0.554688 0.445312 -1 1 -1 z m 0 0" fill="#241f31"/>
|
||||
</svg>
|
After Width: | Height: | Size: 567 B |
4
data/screenshot-ui-window-symbolic.svg
Normal file
4
data/screenshot-ui-window-symbolic.svg
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg height="32px" viewBox="0 0 32 32" width="32px" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m 3 3 c -1.644531 0 -3 1.355469 -3 3 v 14 c 0 1.644531 1.355469 3 3 3 h 4 v 3 c 0 1.644531 1.351562 3 3 3 h 18.996094 c 1.644531 0 3 -1.355469 3 -3 v -14 c 0 -1.644531 -1.355469 -3 -3 -3 h -4 v -3 c 0 -1.644531 -1.355469 -3 -3 -3 z m 0 2 h 18.996094 c 0.570312 0 1 0.429688 1 1 v 3 h -12.996094 c -1.648438 0 -3 1.355469 -3 3 v 9 h -4 c -0.570312 0 -1 -0.429688 -1 -1 v -14 c 0 -0.570312 0.429688 -1 1 -1 z m 7 6 h 18.996094 c 0.570312 0 1 0.429688 1 1 v 14 c 0 0.570312 -0.429688 1 -1 1 h -18.996094 c -0.574219 0 -1 -0.429688 -1 -1 v -14 c 0 -0.570312 0.425781 -1 1 -1 z m 0 0" fill="#241f31"/>
|
||||
</svg>
|
After Width: | Height: | Size: 744 B |
@ -32,6 +32,8 @@
|
||||
<object class="GtkWindow" id="area_chooser_window">
|
||||
<property name="name">area_chooser_window</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="default-height">412</property>
|
||||
<property name="default-width">584</property>
|
||||
<property name="decorated">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="vexpand">True</property>
|
||||
@ -40,13 +42,10 @@
|
||||
<object class="GtkHeaderBar" id="headerbar2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="show-title-buttons">True</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkWindowHandle">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="area_set_button">
|
||||
<property name="name">area_set_button</property>
|
||||
@ -82,6 +81,35 @@
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkMessageDialog" id="progress_dialog">
|
||||
<property name="transient-for">main_window</property>
|
||||
<property name="deletable">False</property>
|
||||
<property name="default-width">300</property>
|
||||
<property name="modal">True</property>
|
||||
<property name="message-type">info</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkProgressBar" id="progressbar">
|
||||
<property name="visible">True</property>
|
||||
<property name="fraction">0.0</property>
|
||||
<property name="show-text">True</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="margin-top">10</property>
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="progressbutton">
|
||||
<property name="visible">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="label" translatable="yes">Finish Recording</property>
|
||||
<property name="margin-top">10</property>
|
||||
<property name="hexpand">True</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkImage" id="image3">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
@ -124,7 +152,7 @@
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="folderchooser">
|
||||
<object class="GtkButton" id="folder_chooser">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
@ -140,12 +168,12 @@
|
||||
<property name="orientation">horizontal</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<object class="GtkImage" id="folderchooserimage">
|
||||
<object class="GtkImage" id="folder_chooser_image">
|
||||
<property name="halign">start</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="folderchooserlabel">
|
||||
<object class="GtkLabel" id="folder_chooser_label">
|
||||
<property name="halign">start</property>
|
||||
</object>
|
||||
</child>
|
||||
@ -174,27 +202,106 @@
|
||||
<property name="margin-bottom">5</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="window_grab_button">
|
||||
<property name="label" translatable="yes">button</property>
|
||||
<object class="GtkToggleButton" id="area_grab_button">
|
||||
<property name="name">area_grab_button</property>
|
||||
<property name="group">area_grab_button</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="margin-start">5</property>
|
||||
<property name="margin-end">5</property>
|
||||
<property name="margin-top">5</property>
|
||||
<property name="margin-bottom">5</property>
|
||||
<property name="margin-start">3</property>
|
||||
<property name="margin-end">3</property>
|
||||
<property name="margin-top">3</property>
|
||||
<property name="margin-bottom">3</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="orientation">horizontal</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<object class="GtkImage" id="area_grab_icon">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label" translatable="yes">Select an Area</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="area_grab_button">
|
||||
<property name="label" translatable="yes">button</property>
|
||||
<object class="GtkToggleButton" id="screen_grab_button">
|
||||
<property name="name">screen_grab_button</property>
|
||||
<property name="group">area_grab_button</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="margin-start">5</property>
|
||||
<property name="margin-end">5</property>
|
||||
<property name="margin-top">5</property>
|
||||
<property name="margin-bottom">5</property>
|
||||
<property name="margin-start">3</property>
|
||||
<property name="margin-end">3</property>
|
||||
<property name="margin-top">3</property>
|
||||
<property name="margin-bottom">3</property>
|
||||
<property name="active">True</property>
|
||||
<child>
|
||||
<object class="GtkGrid">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="column-spacing">3</property>
|
||||
<property name="row-homogeneous">True</property>
|
||||
<child>
|
||||
<object class="GtkImage" id="screen_grab_icon">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label" translatable="yes">Select Screen</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkToggleButton" id="window_grab_button">
|
||||
<property name="name">window_grab_button</property>
|
||||
<property name="group">area_grab_button</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="margin-start">3</property>
|
||||
<property name="margin-end">3</property>
|
||||
<property name="margin-top">3</property>
|
||||
<property name="margin-bottom">3</property>
|
||||
<child>
|
||||
<object class="GtkGrid">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="column-spacing">3</property>
|
||||
<property name="row-homogeneous">True</property>
|
||||
<child>
|
||||
<object class="GtkImage" id="window_grab_icon">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label" translatable="yes">Select a Window</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
@ -453,7 +560,7 @@
|
||||
</object>
|
||||
</child>
|
||||
<child type="end">
|
||||
<object class="GtkButton" id="about_menu_item">
|
||||
<object class="GtkButton" id="aboutbutton">
|
||||
<property name="label">About</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
|
@ -46,6 +46,17 @@ impl AreaCapture {
|
||||
self.height = coordinate.3;
|
||||
*self
|
||||
}
|
||||
|
||||
pub fn reset(&mut self) -> Self {
|
||||
let coordinate = xwininfo_to_coordinate(
|
||||
String::from_utf8(Command::new("xwininfo").arg("-root").output().unwrap().stdout).unwrap()
|
||||
);
|
||||
self.x = coordinate.0;
|
||||
self.y = coordinate.1;
|
||||
self.width = coordinate.2;
|
||||
self.height = coordinate.3;
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
fn xwininfo_to_coordinate(xwininfo_output: String) -> (u16, u16, u16, u16) {
|
||||
|
@ -4,7 +4,6 @@ extern crate dirs;
|
||||
|
||||
use glib::get_user_data_dir;
|
||||
use ini::Ini;
|
||||
use dirs::home_dir;
|
||||
use std::ops::Add;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
@ -34,7 +33,7 @@ fn default() {
|
||||
String::from("file://")
|
||||
.add(
|
||||
glib::get_user_special_dir(glib::UserDirectory::Videos)
|
||||
.unwrap_or(PathBuf::from(std::env::var("HOME").unwrap_or("/".to_string()).as_str()))
|
||||
.unwrap_or_else(|| PathBuf::from(std::env::var("HOME").unwrap_or_else(|_| "/".to_string()).as_str()))
|
||||
.to_str()
|
||||
.unwrap(),
|
||||
)
|
||||
@ -78,7 +77,7 @@ pub fn get(selection: &str, key: &str) -> String {
|
||||
}
|
||||
|
||||
pub fn get_bool(selection: &str, key: &str) -> bool {
|
||||
get(&selection, &key).eq_ignore_ascii_case("1")
|
||||
get(selection, key).eq_ignore_ascii_case("1")
|
||||
}
|
||||
|
||||
pub fn set(selection: &str, key: &str, value: &str) -> bool {
|
||||
@ -91,7 +90,7 @@ pub fn set(selection: &str, key: &str, value: &str) -> bool {
|
||||
}
|
||||
|
||||
pub fn set_bool(selection: &str, key: &str, value: bool) -> bool {
|
||||
set(&selection, &key, if value { "1" } else { "0" })
|
||||
set(selection, key, if value { "1" } else { "0" })
|
||||
}
|
||||
|
||||
pub fn folder_icon(folder_chooser_name: Option<&str>) -> &str {
|
||||
|
@ -5,86 +5,45 @@ use gio::File;
|
||||
use gtk::prelude::*;
|
||||
use gtk::{ButtonsType, DialogFlags, MessageDialog, MessageType, ResponseType};
|
||||
use gtk::{
|
||||
CheckButton, ComboBoxText, Entry, ProgressBar, SpinButton, Window};
|
||||
use std::collections::HashMap;
|
||||
Button, CheckButton, ComboBoxText, Entry, ProgressBar, SpinButton, Window};
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
use std::sync::mpsc;
|
||||
use std::sync::mpsc::{Receiver, Sender};
|
||||
use std::sync::mpsc::Sender;
|
||||
use std::thread::sleep;
|
||||
use std::time::Duration;
|
||||
use subprocess::Exec;
|
||||
use zbus::dbus_proxy;
|
||||
use zvariant::Value;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ProgressWidget {
|
||||
pub window: Window,
|
||||
pub progress: ProgressBar,
|
||||
pub progress_dialog: MessageDialog,
|
||||
pub progressbar: ProgressBar,
|
||||
pub progress_button: Button,
|
||||
}
|
||||
|
||||
impl ProgressWidget {
|
||||
pub fn new(window: &Window) -> ProgressWidget {
|
||||
pub fn new(progress_dialog: MessageDialog, progressbar: ProgressBar, progress_button: Button) -> ProgressWidget {
|
||||
ProgressWidget {
|
||||
window: Window::new(),
|
||||
progress: ProgressBar::new(),
|
||||
progress_dialog,
|
||||
progressbar,
|
||||
progress_button,
|
||||
}
|
||||
.init(&window)
|
||||
}
|
||||
|
||||
pub fn init(self, window: &Window) -> ProgressWidget {
|
||||
self.window.set_title(Some("Progress"));
|
||||
self.window.set_transient_for(Some(window));
|
||||
self.progress.set_fraction(0.0);
|
||||
self.progress.set_show_text(true);
|
||||
self.progress.set_margin_start(10);
|
||||
self.progress.set_margin_top(10);
|
||||
self.progress.set_margin_end(10);
|
||||
self.progress.set_margin_bottom(10);
|
||||
self.window.set_child(Some(&self.progress));
|
||||
self.window.set_deletable(false);
|
||||
self.window.set_modal(true);
|
||||
self.window.set_default_size(200, 50);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_progress(&self, title: String, value: i32, max: i32) {
|
||||
let progress_precentage: f64 = value as f64 / max as f64;
|
||||
self.progress.set_text(Some(&title));
|
||||
self.progress.set_fraction(progress_precentage);
|
||||
self.progressbar.set_text(Some(&title));
|
||||
self.progressbar.set_fraction(progress_precentage);
|
||||
}
|
||||
|
||||
pub fn show(&self) {
|
||||
self.progress.set_fraction(0.0);
|
||||
self.window.show();
|
||||
self.progressbar.set_fraction(0.0);
|
||||
self.progress_dialog.show();
|
||||
}
|
||||
|
||||
pub fn hide(&self) {
|
||||
self.window.hide();
|
||||
self.progress_button.set_sensitive(true);
|
||||
}
|
||||
}
|
||||
|
||||
#[dbus_proxy(
|
||||
interface = "org.gnome.Shell.Screencast",
|
||||
default_path = "/org/gnome/Shell/Screencast"
|
||||
)]
|
||||
trait GnomeScreencast {
|
||||
fn screencast(
|
||||
&self,
|
||||
file_template: &str,
|
||||
options: HashMap<&str, Value>,
|
||||
) -> zbus::Result<(bool, String)>;
|
||||
|
||||
fn screencast_area(
|
||||
&self,
|
||||
x: i32,
|
||||
y: i32,
|
||||
width: i32,
|
||||
height: i32,
|
||||
file_template: &str,
|
||||
options: HashMap<&str, Value>,
|
||||
) -> zbus::Result<(bool, String)>;
|
||||
fn stop_screencast(&self) -> zbus::Result<bool>;
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -125,19 +84,18 @@ impl Ffmpeg {
|
||||
.join(PathBuf::from(format!(
|
||||
"{}.{}",
|
||||
if self.filename.1.text().to_string().trim().eq("") {
|
||||
Utc::now().to_string().replace(" UTC", "").replace(" ", "-")
|
||||
Utc::now().to_string().replace(" UTC", "").replace(' ', "-")
|
||||
} else {
|
||||
self.filename.1.text().to_string().trim().to_string()
|
||||
},
|
||||
self.filename.2.active_id().unwrap().to_string()
|
||||
)))
|
||||
self.filename.2.active_id().unwrap())))
|
||||
.as_path()
|
||||
.display()
|
||||
.to_string(),
|
||||
);
|
||||
|
||||
let is_file_already_exists =
|
||||
std::path::Path::new(format!("{}", self.saved_filename.clone().unwrap()).as_str())
|
||||
std::path::Path::new(self.saved_filename.clone().unwrap().as_str())
|
||||
.exists();
|
||||
|
||||
if is_file_already_exists {
|
||||
@ -164,38 +122,17 @@ impl Ffmpeg {
|
||||
ffmpeg_command.arg("-f");
|
||||
ffmpeg_command.arg("pulse");
|
||||
ffmpeg_command.arg("-i");
|
||||
ffmpeg_command.arg(self.audio_id.active_id().unwrap().to_string());
|
||||
ffmpeg_command.arg(self.audio_id.active_id().unwrap());
|
||||
ffmpeg_command.arg("-f");
|
||||
ffmpeg_command.arg("ogg");
|
||||
ffmpeg_command.arg(format!(
|
||||
"{}.temp.audio",
|
||||
self.saved_filename.as_ref().unwrap().to_string()
|
||||
self.saved_filename.as_ref().unwrap()
|
||||
));
|
||||
ffmpeg_command.arg("-y");
|
||||
self.audio_process_id = Some(ffmpeg_command.spawn().unwrap().id());
|
||||
}
|
||||
|
||||
if is_wayland() {
|
||||
if self.record_video.is_active() {
|
||||
if self.unbound.is_some() {
|
||||
self.clone()
|
||||
.unbound
|
||||
.unwrap()
|
||||
.send(false)
|
||||
.unwrap_or_default();
|
||||
}
|
||||
self.record_wayland(
|
||||
format!("{}.temp", self.saved_filename.as_ref().unwrap().to_string()),
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height,
|
||||
);
|
||||
}
|
||||
|
||||
return (None, self.audio_process_id);
|
||||
}
|
||||
|
||||
if self.record_video.is_active() {
|
||||
let mut ffmpeg_command: Command = Command::new("ffmpeg");
|
||||
|
||||
@ -210,7 +147,7 @@ impl Ffmpeg {
|
||||
ffmpeg_command.arg(format!(
|
||||
"{}+{},{}",
|
||||
std::env::var("DISPLAY")
|
||||
.unwrap_or(":0".to_string())
|
||||
.unwrap_or_else(|_| ":0".to_string())
|
||||
.as_str(),
|
||||
x,
|
||||
y
|
||||
@ -231,7 +168,7 @@ impl Ffmpeg {
|
||||
}
|
||||
ffmpeg_command.arg("-crf");
|
||||
ffmpeg_command.arg("1");
|
||||
ffmpeg_command.arg(self.saved_filename.as_ref().unwrap().to_string());
|
||||
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));
|
||||
@ -244,10 +181,10 @@ impl Ffmpeg {
|
||||
}
|
||||
|
||||
pub fn stop_record(&self) {
|
||||
&self.progress_widget.show();
|
||||
self.progress_widget.show();
|
||||
// kill the process to stop recording
|
||||
if self.video_process_id.is_some() {
|
||||
&self
|
||||
self
|
||||
.progress_widget
|
||||
.set_progress("Stop Recording Video".to_string(), 1, 6);
|
||||
Command::new("kill")
|
||||
@ -257,7 +194,7 @@ impl Ffmpeg {
|
||||
}
|
||||
|
||||
if self.audio_process_id.is_some() {
|
||||
&self
|
||||
self
|
||||
.progress_widget
|
||||
.set_progress("Stop Recording Audio".to_string(), 2, 6);
|
||||
Command::new("kill")
|
||||
@ -270,7 +207,7 @@ impl Ffmpeg {
|
||||
format!(
|
||||
"{}{}",
|
||||
self.saved_filename.as_ref().unwrap_or(&String::from("")),
|
||||
if is_wayland() { ".temp" } else { "" }
|
||||
{ "" }
|
||||
)
|
||||
.as_str(),
|
||||
)
|
||||
@ -284,58 +221,13 @@ impl Ffmpeg {
|
||||
)
|
||||
.exists();
|
||||
|
||||
if is_video_record && is_wayland() {
|
||||
// create new dbus session
|
||||
let connection = zbus::Connection::new_session().unwrap();
|
||||
// bind the connection to gnome screencast proxy
|
||||
let gnome_screencast_proxy = GnomeScreencastProxy::new(&connection).unwrap();
|
||||
gnome_screencast_proxy.stop_screencast().unwrap();
|
||||
if self.unbound.is_some() {
|
||||
&self.progress_widget.set_progress(
|
||||
"Stop Wayland Video Recording".to_string(),
|
||||
3,
|
||||
6,
|
||||
);
|
||||
self.unbound
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.send(true)
|
||||
.unwrap_or_default();
|
||||
|
||||
// convert webm to the format user choose using ffmpeg
|
||||
if is_video_record {
|
||||
let mut ffmpeg_convert_command = Command::new("ffmpeg");
|
||||
ffmpeg_convert_command.arg("-f");
|
||||
ffmpeg_convert_command.arg("webm");
|
||||
ffmpeg_convert_command.arg("-i");
|
||||
ffmpeg_convert_command
|
||||
.arg(format!("{}.temp", self.saved_filename.as_ref().unwrap()));
|
||||
ffmpeg_convert_command.arg(format!(
|
||||
"{}{}",
|
||||
self.saved_filename.as_ref().unwrap_or(&String::new()),
|
||||
if is_audio_record {
|
||||
format!(
|
||||
".temp.without.audio.{}",
|
||||
self.filename.2.active_id().unwrap().to_string()
|
||||
)
|
||||
} else {
|
||||
"".to_string()
|
||||
}
|
||||
));
|
||||
ffmpeg_convert_command.arg("-y");
|
||||
ffmpeg_convert_command.output().unwrap();
|
||||
std::fs::remove_file(format!("{}.temp", self.saved_filename.as_ref().unwrap()))
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if is_video_record && !is_wayland() {
|
||||
if is_video_record {
|
||||
let mut move_command = Command::new("mv");
|
||||
move_command.arg(format!(
|
||||
"{}{}",
|
||||
self.saved_filename.as_ref().unwrap(),
|
||||
if is_wayland() { ".temp" } else { "" }
|
||||
{ "" }
|
||||
));
|
||||
move_command.arg(format!(
|
||||
"{}{}",
|
||||
@ -343,7 +235,7 @@ impl Ffmpeg {
|
||||
if is_audio_record {
|
||||
format!(
|
||||
".temp.without.audio.{}",
|
||||
self.filename.2.active_id().unwrap().to_string()
|
||||
self.filename.2.active_id().unwrap()
|
||||
)
|
||||
} else {
|
||||
"".to_string()
|
||||
@ -353,7 +245,7 @@ impl Ffmpeg {
|
||||
|
||||
// if audio record, then merge video with audio
|
||||
if is_audio_record && is_video_record {
|
||||
&self
|
||||
self
|
||||
.progress_widget
|
||||
.set_progress("Save Audio Recording".to_string(), 4, 6);
|
||||
|
||||
@ -362,7 +254,7 @@ impl Ffmpeg {
|
||||
ffmpeg_audio_merge_command.arg(format!(
|
||||
"{}.temp.without.audio.{}",
|
||||
self.saved_filename.as_ref().unwrap(),
|
||||
self.filename.2.active_id().unwrap().to_string()
|
||||
self.filename.2.active_id().unwrap()
|
||||
));
|
||||
ffmpeg_audio_merge_command.arg("-i");
|
||||
ffmpeg_audio_merge_command.arg(format!(
|
||||
@ -385,14 +277,14 @@ impl Ffmpeg {
|
||||
std::fs::remove_file(format!(
|
||||
"{}.temp.without.audio.{}",
|
||||
self.saved_filename.as_ref().unwrap(),
|
||||
self.filename.2.active_id().unwrap().to_string()
|
||||
self.filename.2.active_id().unwrap()
|
||||
))
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
// if only audio is recording then convert it to chosen fromat
|
||||
else if is_audio_record && !is_video_record {
|
||||
&self
|
||||
self
|
||||
.progress_widget
|
||||
.set_progress("Convert Audio to choosen format".to_string(), 4, 6);
|
||||
sleep(Duration::from_secs(1));
|
||||
@ -404,7 +296,7 @@ impl Ffmpeg {
|
||||
"{}.temp.audio",
|
||||
self.saved_filename.as_ref().unwrap()
|
||||
))
|
||||
.arg(format!("{}", self.saved_filename.as_ref().unwrap()))
|
||||
.arg(self.saved_filename.as_ref().unwrap())
|
||||
.output()
|
||||
.unwrap();
|
||||
std::fs::remove_file(format!(
|
||||
@ -415,55 +307,20 @@ impl Ffmpeg {
|
||||
}
|
||||
|
||||
// execute command after finish recording
|
||||
if !(self.command.text().trim() == "") {
|
||||
&self.progress_widget.set_progress(
|
||||
if self.command.text().trim() != "" {
|
||||
self.progress_widget.set_progress(
|
||||
"execute custom command after finish".to_string(),
|
||||
5,
|
||||
6,
|
||||
6
|
||||
);
|
||||
Exec::shell(self.command.text().trim()).popen().unwrap();
|
||||
}
|
||||
|
||||
&self
|
||||
self
|
||||
.progress_widget
|
||||
.set_progress("Finish".to_string(), 6, 6);
|
||||
&self.progress_widget.hide();
|
||||
}
|
||||
self.progress_widget.hide();
|
||||
|
||||
// Gnome screencast for record wayland
|
||||
pub fn record_wayland(&mut self, filename: String, x: u16, y: u16, width: u16, height: u16) {
|
||||
// create new dbus session
|
||||
let connection = zbus::Connection::new_session().unwrap();
|
||||
// bind the connection to gnome screencast proxy
|
||||
let gnome_screencast_proxy = GnomeScreencastProxy::new(&connection).unwrap();
|
||||
// options for gnome screencast
|
||||
let mut screencast_options: HashMap<&str, Value> = HashMap::new();
|
||||
screencast_options.insert("framerate", Value::new(self.record_frames.value()));
|
||||
screencast_options.insert("draw-cursor", Value::new(self.record_mouse.is_active()));
|
||||
screencast_options.insert("pipeline", Value::new("vp8enc min_quantizer=10 max_quantizer=50 cq_level=13 cpu-used=5 deadline=1000000 threads=%T ! queue ! webmmux"));
|
||||
// make unbound channel for communication with record thread
|
||||
let (tx, tr): (Sender<bool>, Receiver<bool>) = mpsc::channel();
|
||||
self.unbound = Some(tx);
|
||||
|
||||
// start recording in another thread
|
||||
std::thread::spawn(move || {
|
||||
gnome_screencast_proxy
|
||||
.screencast_area(
|
||||
x.into(),
|
||||
y.into(),
|
||||
width.into(),
|
||||
height.into(),
|
||||
&filename,
|
||||
screencast_options,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
loop {
|
||||
if tr.recv().unwrap_or(false) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
pub fn play_record(self) {
|
||||
@ -477,7 +334,7 @@ impl Ffmpeg {
|
||||
.unwrap();
|
||||
} else {
|
||||
Command::new("xdg-open")
|
||||
.arg(self.saved_filename.unwrap())
|
||||
.arg(self.saved_filename.as_ref().unwrap())
|
||||
.spawn()
|
||||
.unwrap();
|
||||
}
|
||||
@ -485,12 +342,6 @@ impl Ffmpeg {
|
||||
}
|
||||
}
|
||||
|
||||
fn is_wayland() -> bool {
|
||||
std::env::var("XDG_SESSION_TYPE")
|
||||
.unwrap_or_default()
|
||||
.eq_ignore_ascii_case("wayland")
|
||||
}
|
||||
|
||||
fn is_snap() -> bool {
|
||||
std::env::var("SNAP").unwrap_or_default().len() > 0
|
||||
std::env::var("SNAP").unwrap_or_default().is_empty()
|
||||
}
|
||||
|
235
src/main.rs
235
src/main.rs
@ -9,8 +9,7 @@ mod ffmpeg_interface;
|
||||
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, SpinButton, Window};
|
||||
//use libappindicator::{AppIndicator, AppIndicatorStatus};
|
||||
use gtk::{AboutDialog, Builder, Button, CheckButton, ComboBoxText, CssProvider, Entry, FileChooserNative, FileChooserAction, Image, Label, MessageDialog, ProgressBar, SpinButton, ToggleButton, Window};
|
||||
use std::cell::RefCell;
|
||||
use std::ops::Add;
|
||||
use std::path::Path;
|
||||
@ -31,6 +30,7 @@ pub fn build_ui(application: &Application) {
|
||||
println!("Failed to initialize GTK.");
|
||||
return;
|
||||
}
|
||||
// TODO: add wayland screen record support
|
||||
|
||||
let ui_src = include_str!("../interfaces/main.ui").to_string();
|
||||
let builder: Builder = Builder::from_string(ui_src.as_str());
|
||||
@ -45,7 +45,7 @@ pub fn build_ui(application: &Application) {
|
||||
|
||||
if !po_path_abs.exists() {
|
||||
po_path_abs = std::fs::canonicalize(Path::new(
|
||||
&std::env::var("PO_DIR").unwrap_or(String::from("po")),
|
||||
&std::env::var("PO_DIR").unwrap_or_else(|_| String::from("po")),
|
||||
))
|
||||
.unwrap();
|
||||
}
|
||||
@ -60,9 +60,10 @@ pub fn build_ui(application: &Application) {
|
||||
// get Objects from UI
|
||||
let main_window: Window = builder.object("main_window").unwrap();
|
||||
let area_chooser_window: Window = builder.object("area_chooser_window").unwrap();
|
||||
let area_grab_button: Button = builder.object("area_grab_button").unwrap();
|
||||
let area_grab_button: ToggleButton = builder.object("area_grab_button").unwrap();
|
||||
let area_grab_icon: Image = builder.object("area_grab_icon").unwrap();
|
||||
let area_set_button: Button = builder.object("area_set_button").unwrap();
|
||||
let about_menu_item: Button = builder.object("about_menu_item").unwrap();
|
||||
let about_button: Button = builder.object("aboutbutton").unwrap();
|
||||
let about_dialog: AboutDialog = builder.object("about_dialog").unwrap();
|
||||
let audio_source_combobox: ComboBoxText = builder.object("audiosource").unwrap();
|
||||
let audio_source_label: Label = builder.object("audio_source_label").unwrap();
|
||||
@ -72,20 +73,25 @@ pub fn build_ui(application: &Application) {
|
||||
let delay_label: Label = builder.object("delay_label").unwrap();
|
||||
let delay_spin: SpinButton = builder.object("delay").unwrap();
|
||||
let filename_entry: Entry = builder.object("filename").unwrap();
|
||||
let folder_chooser_button: Button = builder.object("folderchooser").unwrap();
|
||||
let folder_chooser_image: Image = builder.object("folderchooserimage").unwrap();
|
||||
let folder_chooser_label: Label = builder.object("folderchooserlabel").unwrap();
|
||||
let folder_chooser_button: Button = builder.object("folder_chooser").unwrap();
|
||||
let folder_chooser_image: Image = builder.object("folder_chooser_image").unwrap();
|
||||
let folder_chooser_label: Label = builder.object("folder_chooser_label").unwrap();
|
||||
let follow_mouse_switch: CheckButton = builder.object("followmouseswitch").unwrap();
|
||||
let format_chooser_combobox: ComboBoxText = builder.object("comboboxtext1").unwrap();
|
||||
let frames_label: Label = builder.object("frames_label").unwrap();
|
||||
let frames_spin: SpinButton = builder.object("frames").unwrap();
|
||||
let mouse_switch: CheckButton = builder.object("mouseswitch").unwrap();
|
||||
let play_button: Button = builder.object("playbutton").unwrap();
|
||||
let progress_button: Button = builder.object("progressbutton").unwrap();
|
||||
let progress_dialog: MessageDialog = builder.object("progress_dialog").unwrap();
|
||||
let progressbar: ProgressBar = builder.object("progressbar").unwrap();
|
||||
let record_button: Button = builder.object("recordbutton").unwrap();
|
||||
let screen_grab_button: ToggleButton = builder.object("screen_grab_button").unwrap();
|
||||
let screen_grab_icon: Image = builder.object("screen_grab_icon").unwrap();
|
||||
let stop_button: Button = builder.object("stopbutton").unwrap();
|
||||
let video_switch: CheckButton = builder.object("videoswitch").unwrap();
|
||||
let window_grab_button: Button = builder.object("window_grab_button").unwrap();
|
||||
// TODO: add recording mode indicator
|
||||
let window_grab_icon: Image = builder.object("window_grab_icon").unwrap();
|
||||
let window_grab_button: ToggleButton = builder.object("window_grab_button").unwrap();
|
||||
// TODO: add timer
|
||||
|
||||
// --- default properties
|
||||
@ -105,17 +111,17 @@ pub fn build_ui(application: &Application) {
|
||||
command_entry.set_text(&config_management::get("default", "command"));
|
||||
|
||||
// CheckBox
|
||||
format_chooser_combobox.append(Some("webm"), &gettext("WEBM (Open Web Media File)"));
|
||||
format_chooser_combobox.append(Some("mp4"), &gettext("MP4 (MPEG-4 Part 14)"));
|
||||
format_chooser_combobox.append(Some("gif"), &gettext("GIF (Graphics Interchange Format)"));
|
||||
format_chooser_combobox.append(
|
||||
Some("mkv"),
|
||||
&gettext("MKV (Matroska multimedia container format)"),
|
||||
);
|
||||
format_chooser_combobox.append(Some("avi"), &gettext("AVI (Audio Video Interleaved)"));
|
||||
format_chooser_combobox.append(Some("mp4"), &gettext("MP4 (MPEG-4 Part 14)"));
|
||||
format_chooser_combobox.append(Some("wmv"), &gettext("WMV (Windows Media Video)"));
|
||||
format_chooser_combobox.append(Some("gif"), &gettext("GIF (Graphics Interchange Format)"));
|
||||
format_chooser_combobox.append(Some("nut"), &gettext("NUT (NUT Recording Format)"));
|
||||
format_chooser_combobox.set_active(Some(0));
|
||||
// TODO: add support for webm format
|
||||
|
||||
// get audio sources
|
||||
let sources_descriptions: Vec<String> = {
|
||||
@ -124,7 +130,7 @@ pub fn build_ui(application: &Application) {
|
||||
.stdout(Stdio::piped())
|
||||
.spawn();
|
||||
let sources_descriptions = String::from_utf8(
|
||||
if list_sources_child.is_ok() {
|
||||
if let Ok(..) = list_sources_child {
|
||||
Command::new("grep")
|
||||
.args(&["-e", "device.description"])
|
||||
.stdin(
|
||||
@ -143,13 +149,13 @@ pub fn build_ui(application: &Application) {
|
||||
)
|
||||
.unwrap();
|
||||
sources_descriptions
|
||||
.split("\n")
|
||||
.split('\n')
|
||||
.map(|s| {
|
||||
s.trim()
|
||||
.replace("device.description = ", "")
|
||||
.replace("\"", "")
|
||||
.replace('\"', "")
|
||||
})
|
||||
.filter(|s| s != "")
|
||||
.filter(|s| !s.is_empty())
|
||||
.collect()
|
||||
};
|
||||
|
||||
@ -160,6 +166,7 @@ pub fn build_ui(application: &Application) {
|
||||
audio_source_combobox.set_active(Some(0));
|
||||
|
||||
// Switchs
|
||||
let _audio_switch = audio_switch.clone();
|
||||
video_switch.set_label(Some(&gettext("Record Video")));
|
||||
audio_switch.set_label(Some(&gettext("Record Audio")));
|
||||
mouse_switch.set_label(Some(&gettext("Show Mouse")));
|
||||
@ -198,8 +205,57 @@ pub fn build_ui(application: &Application) {
|
||||
});
|
||||
|
||||
// Buttons
|
||||
window_grab_button.set_label(&gettext("Select a Window"));
|
||||
area_grab_button.set_label(&gettext("Select an Area"));
|
||||
let mut area_icon_path = {
|
||||
let mut current_exec_dir = std::env::current_exe().unwrap();
|
||||
current_exec_dir.pop();
|
||||
current_exec_dir
|
||||
}
|
||||
.join(Path::new("data/screenshot-ui-area-symbolic.svg"));
|
||||
|
||||
if !area_icon_path.exists() {
|
||||
area_icon_path = std::fs::canonicalize(Path::new(
|
||||
&std::env::var("DATA_DIR")
|
||||
.unwrap_or_else(|_| String::from("data/"))
|
||||
.add("screenshot-ui-area-symbolic.svg"),
|
||||
))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
let mut screen_icon_path = {
|
||||
let mut current_exec_dir = std::env::current_exe().unwrap();
|
||||
current_exec_dir.pop();
|
||||
current_exec_dir
|
||||
}
|
||||
.join(Path::new("data/screenshot-ui-display-symbolic.svg"));
|
||||
|
||||
if !screen_icon_path.exists() {
|
||||
screen_icon_path = std::fs::canonicalize(Path::new(
|
||||
&std::env::var("DATA_DIR")
|
||||
.unwrap_or_else(|_| String::from("data/"))
|
||||
.add("screenshot-ui-display-symbolic.svg"),
|
||||
))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
let mut window_icon_path = {
|
||||
let mut current_exec_dir = std::env::current_exe().unwrap();
|
||||
current_exec_dir.pop();
|
||||
current_exec_dir
|
||||
}
|
||||
.join(Path::new("data/screenshot-ui-window-symbolic.svg"));
|
||||
|
||||
if !window_icon_path.exists() {
|
||||
window_icon_path = std::fs::canonicalize(Path::new(
|
||||
&std::env::var("DATA_DIR")
|
||||
.unwrap_or_else(|_| String::from("data/"))
|
||||
.add("screenshot-ui-window-symbolic.svg"),
|
||||
))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
area_grab_icon.set_from_file(Some(area_icon_path));
|
||||
screen_grab_icon.set_from_file(Some(screen_icon_path));
|
||||
window_grab_icon.set_from_file(Some(&window_icon_path));
|
||||
|
||||
// Labels
|
||||
command_label.set_label(&gettext("Run Command After Recording:"));
|
||||
@ -208,18 +264,6 @@ 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")
|
||||
.to_string()
|
||||
.parse::<f64>()
|
||||
.unwrap(),
|
||||
);
|
||||
delay_spin.set_value(
|
||||
config_management::get("default", "delay")
|
||||
.to_string()
|
||||
.parse::<f64>()
|
||||
.unwrap(),
|
||||
);
|
||||
let _frames_spin = frames_spin.to_owned();
|
||||
frames_spin.connect_value_changed(move |_| {
|
||||
config_management::set(
|
||||
@ -246,10 +290,10 @@ pub fn build_ui(application: &Application) {
|
||||
Some("Cancel"),
|
||||
);
|
||||
folder_chooser_native.set_modal(true);
|
||||
let mut folder_chooser = Some(gio::File::for_uri(&config_management::get("default", "folder"))).unwrap();
|
||||
let mut folder_chooser_name = folder_chooser.basename().unwrap();
|
||||
let folder_chooser = Some(gio::File::for_uri(&config_management::get("default", "folder"))).unwrap();
|
||||
let folder_chooser_name = folder_chooser.basename().unwrap();
|
||||
folder_chooser_label.set_label(&folder_chooser_name.to_string_lossy());
|
||||
let mut folder_chooser_icon = config_management::folder_icon(folder_chooser_name.to_str());
|
||||
let folder_chooser_icon = config_management::folder_icon(folder_chooser_name.to_str());
|
||||
folder_chooser_image.set_icon_name(Some(folder_chooser_icon));
|
||||
// show file chooser dialog
|
||||
folder_chooser_button.connect_clicked(glib::clone!(@strong folder_chooser_native => move |_| {
|
||||
@ -258,7 +302,7 @@ pub fn build_ui(application: &Application) {
|
||||
let folder_chooser = folder_chooser_native.file().unwrap();
|
||||
let folder_chooser_name = folder_chooser.basename().unwrap();
|
||||
folder_chooser_label.set_label(&folder_chooser_name.to_string_lossy());
|
||||
let mut folder_chooser_icon = config_management::folder_icon(folder_chooser_name.to_str());
|
||||
let folder_chooser_icon = config_management::folder_icon(folder_chooser_name.to_str());
|
||||
folder_chooser_image.set_icon_name(Some(folder_chooser_icon));
|
||||
};
|
||||
folder_chooser_native.destroy();
|
||||
@ -269,7 +313,7 @@ pub fn build_ui(application: &Application) {
|
||||
// --- connections
|
||||
// show dialog window when about button clicked then hide it after close
|
||||
let _about_dialog: AboutDialog = about_dialog.to_owned();
|
||||
about_menu_item.connect_clicked(move |_| {
|
||||
about_button.connect_clicked(move |_| {
|
||||
_about_dialog.show();
|
||||
_about_dialog.set_hide_on_close(true);
|
||||
});
|
||||
@ -277,10 +321,6 @@ pub fn build_ui(application: &Application) {
|
||||
// Buttons
|
||||
let area_capture: Rc<RefCell<area_capture::AreaCapture>> =
|
||||
Rc::new(RefCell::new(area_capture::AreaCapture::new()));
|
||||
let mut _area_capture = area_capture.clone();
|
||||
window_grab_button.connect_clicked(move |_| {
|
||||
_area_capture.borrow_mut().get_area();
|
||||
});
|
||||
|
||||
let _area_chooser_window = area_chooser_window.clone();
|
||||
let mut _area_capture = area_capture.clone();
|
||||
@ -297,6 +337,26 @@ pub fn build_ui(application: &Application) {
|
||||
_area_chooser_window.hide();
|
||||
});
|
||||
|
||||
let _area_chooser_window = area_chooser_window.clone();
|
||||
let mut _area_capture = area_capture.clone();
|
||||
screen_grab_button.connect_clicked(move |_| {
|
||||
_area_chooser_window.hide();
|
||||
_area_capture.borrow_mut().reset();
|
||||
});
|
||||
|
||||
let _area_chooser_window = area_chooser_window.clone();
|
||||
let mut _area_capture = area_capture.clone();
|
||||
window_grab_button.connect_clicked(move |_| {
|
||||
_area_chooser_window.hide();
|
||||
_area_capture.borrow_mut().get_area();
|
||||
});
|
||||
|
||||
let _progress_button = progress_button.clone();
|
||||
let _progress_dialog = progress_dialog.clone();
|
||||
_progress_button.connect_clicked(move |_| {
|
||||
_progress_dialog.hide();
|
||||
});
|
||||
|
||||
// init record struct
|
||||
let ffmpeg_record_interface: Rc<RefCell<Ffmpeg>> = Rc::new(RefCell::new(Ffmpeg {
|
||||
filename: (folder_chooser, filename_entry, format_chooser_combobox),
|
||||
@ -312,63 +372,15 @@ pub fn build_ui(application: &Application) {
|
||||
audio_process_id: None,
|
||||
saved_filename: None,
|
||||
unbound: None,
|
||||
progress_widget: ProgressWidget::new(&main_window),
|
||||
progress_widget: ProgressWidget::new(progress_dialog, progressbar, progress_button),
|
||||
}));
|
||||
|
||||
// App Indicator
|
||||
let mut indicator_icon_path = {
|
||||
let mut current_exec_dir = std::env::current_exe().unwrap();
|
||||
current_exec_dir.pop();
|
||||
current_exec_dir
|
||||
}
|
||||
.join(Path::new("data/blue-recorder@x96.png"));
|
||||
|
||||
if !indicator_icon_path.exists() {
|
||||
indicator_icon_path = std::fs::canonicalize(Path::new(
|
||||
&std::env::var("DATA_DIR")
|
||||
.unwrap_or(String::from("data/"))
|
||||
.add("blue-recorder@x96.png"),
|
||||
))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
//let indicator = Rc::new(RefCell::new(AppIndicator::new(
|
||||
//"Blue Recorder",
|
||||
//indicator_icon_path.to_str().unwrap(),
|
||||
//)));
|
||||
//indicator
|
||||
//.clone()
|
||||
//.borrow_mut()
|
||||
//.set_status(AppIndicatorStatus::Passive);
|
||||
//let mut menu = gtk::Popover::new();
|
||||
//let indicator_stop_recording = Label::new(Some(&gettext("stop recording")));
|
||||
//menu.set_child(Some(&indicator_stop_recording));
|
||||
//menu.show();
|
||||
//indicator.clone().borrow_mut().set_menu(&mut menu); // indicator support GtkMenu from Gtk3
|
||||
// when indictor stop recording button clicked
|
||||
//let mut _ffmpeg_record_interface = ffmpeg_record_interface.clone();
|
||||
//let mut _indicator = indicator.clone();
|
||||
//let _stop_button = stop_button.clone();
|
||||
//let _play_button = play_button.clone();
|
||||
//let _record_button = record_button.clone();
|
||||
//indicator_stop_recording.connect_activate_current_link(move |_| {
|
||||
//_ffmpeg_record_interface.borrow_mut().clone().stop_record();
|
||||
//_indicator
|
||||
//.borrow_mut()
|
||||
//.set_status(AppIndicatorStatus::Passive);
|
||||
|
||||
//_record_button.show();
|
||||
//_stop_button.hide();
|
||||
//_play_button.show();
|
||||
//});
|
||||
|
||||
let mut _ffmpeg_record_interface = ffmpeg_record_interface.clone();
|
||||
let mut _area_capture = area_capture.clone();
|
||||
//let mut _indicator = indicator.clone();
|
||||
let _stop_button = stop_button.clone();
|
||||
let _record_button = record_button.clone();
|
||||
record_button.connect_clicked(move |_| {
|
||||
let _area_capture = _area_capture.borrow_mut().clone();
|
||||
let _area_capture = area_capture.borrow_mut();
|
||||
match _ffmpeg_record_interface.borrow_mut().start_record(
|
||||
_area_capture.x,
|
||||
_area_capture.y,
|
||||
@ -376,13 +388,13 @@ pub fn build_ui(application: &Application) {
|
||||
_area_capture.height,
|
||||
) {
|
||||
(None, None) => {
|
||||
// do nothing if the start_record function return nothing
|
||||
// do nothing if the start_record function return nothing
|
||||
if _audio_switch.is_active() {
|
||||
_record_button.hide();
|
||||
_stop_button.show();
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
//_indicator
|
||||
//.borrow_mut()
|
||||
//.set_status(AppIndicatorStatus::Active);
|
||||
|
||||
_record_button.hide();
|
||||
_stop_button.show();
|
||||
}
|
||||
@ -390,16 +402,11 @@ pub fn build_ui(application: &Application) {
|
||||
});
|
||||
|
||||
let mut _ffmpeg_record_interface = ffmpeg_record_interface.clone();
|
||||
//let mut _indicator = indicator.clone();
|
||||
let _stop_button = stop_button.clone();
|
||||
let _play_button = play_button.clone();
|
||||
let _record_button = record_button.clone();
|
||||
stop_button.connect_clicked(move |_| {
|
||||
let _record_button = record_button.clone();
|
||||
_ffmpeg_record_interface.borrow_mut().clone().stop_record();
|
||||
//_indicator
|
||||
//.borrow_mut()
|
||||
//.set_status(AppIndicatorStatus::Passive);
|
||||
|
||||
_record_button.show();
|
||||
_stop_button.hide();
|
||||
_play_button.show();
|
||||
@ -411,7 +418,23 @@ pub fn build_ui(application: &Application) {
|
||||
});
|
||||
|
||||
// About Dialog
|
||||
let logo = Image::from_file(&indicator_icon_path.to_str().unwrap());
|
||||
let mut about_icon_path = {
|
||||
let mut current_exec_dir = std::env::current_exe().unwrap();
|
||||
current_exec_dir.pop();
|
||||
current_exec_dir
|
||||
}
|
||||
.join(Path::new("data/blue-recorder@x96.png"));
|
||||
|
||||
if !about_icon_path.exists() {
|
||||
about_icon_path = std::fs::canonicalize(Path::new(
|
||||
&std::env::var("DATA_DIR")
|
||||
.unwrap_or_else(|_| String::from("data/"))
|
||||
.add("blue-recorder@x96.png"),
|
||||
))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
let logo = Image::from_file(&about_icon_path.to_str().unwrap());
|
||||
about_dialog.set_transient_for(Some(&main_window));
|
||||
about_dialog.set_program_name(Some(&gettext("Blue Recorder")));
|
||||
about_dialog.set_version(Some("0.2.0"));
|
||||
@ -444,14 +467,10 @@ pub fn build_ui(application: &Application) {
|
||||
});
|
||||
|
||||
// close the application when main window destroy
|
||||
let mut _ffmpeg_record_interface = ffmpeg_record_interface.clone();
|
||||
//let mut _indicator = indicator.clone();
|
||||
main_window.connect_destroy(move |main_window| {
|
||||
// stop recording before close the application
|
||||
let mut _ffmpeg_record_interface = ffmpeg_record_interface.clone();
|
||||
// stop recording before close the application
|
||||
_ffmpeg_record_interface.borrow_mut().clone().stop_record();
|
||||
//_indicator
|
||||
//.borrow_mut()
|
||||
//.set_status(AppIndicatorStatus::Passive);
|
||||
main_window.close();
|
||||
});
|
||||
|
||||
|
@ -7,3 +7,18 @@
|
||||
color: rgba(255, 255, 255, 1);
|
||||
background: rgba(255, 255, 255, 0);
|
||||
}
|
||||
|
||||
#area_grab_button:checked{
|
||||
color: rgba(255, 255, 255, 1);
|
||||
background: rgba(32.0, 74.0, 135, 1);
|
||||
}
|
||||
|
||||
#screen_grab_button:checked{
|
||||
color: rgba(255, 255, 255, 1);
|
||||
background: rgba(32.0, 74.0, 135, 1);
|
||||
}
|
||||
|
||||
#window_grab_button:checked{
|
||||
color: rgba(255, 255, 255, 1);
|
||||
background: rgba(32.0, 74.0, 135, 1);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user