mirror of
https://github.com/xlmnxp/blue-recorder.git
synced 2025-01-18 08:21:46 +03:00
Initial gtk4 migration
This commit is contained in:
parent
9b4ec9bb05
commit
6f48df3a6a
1251
Cargo.lock
generated
1251
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
24
Cargo.toml
24
Cargo.toml
@ -1,28 +1,24 @@
|
||||
[package]
|
||||
name = "blue-recorder"
|
||||
version = "0.1.5"
|
||||
authors = ["Salem Yaslem <s@sy.sa>"]
|
||||
edition = "2018"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
gdk = "0.13.2"
|
||||
chrono = "0.4.19"
|
||||
gdk = { git = "https://github.com/gtk-rs/gtk4-rs.git", package = "gdk4"}
|
||||
gdk-pixbuf = "0.9.0"
|
||||
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"
|
||||
chrono = "0.4.19"
|
||||
libappindicator = "0.5.2"
|
||||
gettext-rs = "0.7.0"
|
||||
subprocess = "0.2.6"
|
||||
zbus = "1.9.2"
|
||||
zvariant = "2.10.0"
|
||||
gdk-pixbuf = "0.9.0"
|
||||
|
||||
[dependencies.gtk]
|
||||
version = "0.9.0"
|
||||
features = ["v3_16"]
|
||||
|
||||
[dependencies.gio]
|
||||
version = "0.9.0"
|
||||
features = ["v2_44"]
|
||||
version = "0.15.0"
|
||||
|
1027
interfaces/main.ui
1027
interfaces/main.ui
File diff suppressed because it is too large
Load Diff
143
po/tr.po
143
po/tr.po
@ -1,143 +0,0 @@
|
||||
# Turkish translation for Blue Recorder.
|
||||
# Copyright (C) 2022 Blue Recorder's COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the Blue Recorder package.
|
||||
#
|
||||
# Sabri Ünal <libreajans@gmail.com>, 2022.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"POT-Creation-Date: 2017-08-08 10:53+0300\n"
|
||||
"PO-Revision-Date: 2022-08-27 02:15+0300\n"
|
||||
"Last-Translator: Sabri Ünal <libreajans@gmail.com>\n"
|
||||
"Language-Team: Turkish <gnometurk@gnome.org>\n"
|
||||
"Language: tr\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"Generated-By: pygettext.py 1.5\n"
|
||||
"X-Generator: Poedit 3.1.1\n"
|
||||
|
||||
msgid ""
|
||||
"There seems to be a problem in recording. Try running 'blue-recorder' from "
|
||||
"the command line to see the issue."
|
||||
msgstr ""
|
||||
"Kayıtta bir sorun var gibi görünüyor. Sorunu görmek için 'blue-recorder' "
|
||||
"uygulamasını komut satırından çalıştırmayı deneyin."
|
||||
|
||||
msgid "Stop Recording"
|
||||
msgstr "Kaydetmeyi Durdur"
|
||||
|
||||
msgid "Recording has started!"
|
||||
msgstr "Kayıt başlatıldı!"
|
||||
|
||||
msgid "Recording has stopped!"
|
||||
msgstr "Kayıt durduruldu!"
|
||||
|
||||
msgid ""
|
||||
"Your GIF image is currently being processed, this may take a while according "
|
||||
"to your PC's resources."
|
||||
msgstr ""
|
||||
"GIF resminiz şu anda işleniyor. Bilgisayarınızın kaynaklarına göre bu işlem "
|
||||
"biraz sürebilir."
|
||||
|
||||
msgid "File already exists!"
|
||||
msgstr "Dosya zaten var!"
|
||||
|
||||
msgid "Would you like to overwrite this file?"
|
||||
msgstr "Bu dosyanın üzerine yazmak ister misiniz?"
|
||||
|
||||
msgid "Sorry Jim, looks like you are using something we don't support"
|
||||
msgstr "Üzgünüm. Desteklemediğimiz bir şey kullanıyor gibisiniz"
|
||||
|
||||
msgid "About"
|
||||
msgstr "Hakkında"
|
||||
|
||||
msgid "Blue Recorder"
|
||||
msgstr "Blue Recorder"
|
||||
|
||||
msgid "AreaChooser"
|
||||
msgstr "Alan Seçici"
|
||||
|
||||
msgid "File Name.."
|
||||
msgstr "Dosya Adı.."
|
||||
|
||||
msgid "Enter your command here.."
|
||||
msgstr "Komutu buraya girin.."
|
||||
|
||||
msgid "MKV (Matroska multimedia container format)"
|
||||
msgstr "MKV"
|
||||
|
||||
msgid "AVI (Audio Video Interleaved)"
|
||||
msgstr "AVI"
|
||||
|
||||
msgid "MP4 (MPEG-4 Part 14)"
|
||||
msgstr "MP4"
|
||||
|
||||
msgid "WMV (Windows Media Video)"
|
||||
msgstr "WMV (Windows Media Videosu)"
|
||||
|
||||
msgid "GIF (Graphics Interchange Format)"
|
||||
msgstr "GIF"
|
||||
|
||||
msgid "NUT (NUT Recording Format)"
|
||||
msgstr "NUT (NUT Kayıt Biçimi)"
|
||||
|
||||
msgid "Record Video"
|
||||
msgstr "Video Kaydet"
|
||||
|
||||
msgid "Record Audio"
|
||||
msgstr "Ses Kaydet"
|
||||
|
||||
msgid "Show Mouse"
|
||||
msgstr "Fareyi Göster"
|
||||
|
||||
msgid "Follow Mouse"
|
||||
msgstr "Fareyi Takip Et"
|
||||
|
||||
msgid "A simple screen recorder for Linux desktop. Supports Wayland & Xorg."
|
||||
msgstr ""
|
||||
"Linux masaüstü için basit bir ekran kaydedici. Wayland ve Xorg'u destekler."
|
||||
|
||||
msgid "Select a Window"
|
||||
msgstr "Pencere Seç"
|
||||
|
||||
msgid "Select an Area"
|
||||
msgstr "Alan Seç"
|
||||
|
||||
msgid "Frames:"
|
||||
msgstr "Kare:"
|
||||
|
||||
msgid "Delay:"
|
||||
msgstr "Gecikme:"
|
||||
|
||||
msgid "Run Command After Recording:"
|
||||
msgstr "Kayıttan Sonra Komut Çalıştır:"
|
||||
|
||||
msgid "Audio Input Source:"
|
||||
msgstr "Ses Girdi Kaynağı:"
|
||||
|
||||
msgid "Default PulseAudio Input Source"
|
||||
msgstr "Öntanımlı PulseAudio Girdi Kaynağı"
|
||||
|
||||
msgid ""
|
||||
"You didn't run the program using the application icon (desktop file). This "
|
||||
"will cause the program not to work. Run it using the icon from the menus "
|
||||
"only. (Need to export GDK_BACKEND=x11 first)"
|
||||
msgstr ""
|
||||
"Programı uygulama simgesini (desktop dosyası) kullanarak çalıştırmadınız. "
|
||||
"Bu, programın çalışmamasına neden olacaktır. Yalnızca menülerdeki simgeyi "
|
||||
"kullanarak çalıştırın. (Önce GDK_BACKEND=x11'i dışa aktarmanız gerekir)"
|
||||
|
||||
msgid "Your window position has been saved!"
|
||||
msgstr "Pencere konumunuz kaydedildi!"
|
||||
|
||||
msgid "Area Chooser"
|
||||
msgstr "Alan Seçici"
|
||||
|
||||
msgid "Your area position has been saved!"
|
||||
msgstr "Alan konumunuz kaydedildi!"
|
||||
|
||||
msgid "stop recording"
|
||||
msgstr "kaydı durdur"
|
4
src/config_management.rs
Normal file → Executable file
4
src/config_management.rs
Normal file → Executable file
@ -28,9 +28,7 @@ pub fn initialize() -> PathBuf {
|
||||
fn default() {
|
||||
set("default", "frame", "60");
|
||||
set("default", "delay", "0");
|
||||
set(
|
||||
"default",
|
||||
"folder",
|
||||
set("default", "folder",
|
||||
String::from("file://")
|
||||
.add(
|
||||
glib::get_user_special_dir(glib::UserDirectory::Videos)
|
||||
|
@ -1,12 +1,11 @@
|
||||
extern crate subprocess;
|
||||
use chrono::prelude::*;
|
||||
use gettextrs::gettext;
|
||||
use gio::File;
|
||||
use gtk::prelude::*;
|
||||
use gtk::{ButtonsType, DialogFlags, MessageDialog, MessageType, ResponseType};
|
||||
use gtk::{
|
||||
CheckButton, ComboBoxText, Entry, FileChooser, ProgressBar, SpinButton, Window, WindowPosition,
|
||||
WindowType,
|
||||
};
|
||||
CheckButton, ComboBoxText, Entry, ProgressBar, SpinButton, Window};
|
||||
use std::collections::HashMap;
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
@ -27,14 +26,14 @@ pub struct ProgressWidget {
|
||||
impl ProgressWidget {
|
||||
pub fn new(window: &Window) -> ProgressWidget {
|
||||
ProgressWidget {
|
||||
window: Window::new(WindowType::Toplevel),
|
||||
window: Window::new(),
|
||||
progress: ProgressBar::new(),
|
||||
}
|
||||
.init(&window)
|
||||
}
|
||||
|
||||
pub fn init(self, window: &Window) -> ProgressWidget {
|
||||
self.window.set_title("Progress");
|
||||
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);
|
||||
@ -42,11 +41,10 @@ impl ProgressWidget {
|
||||
self.progress.set_margin_top(10);
|
||||
self.progress.set_margin_end(10);
|
||||
self.progress.set_margin_bottom(10);
|
||||
self.window.add(&self.progress);
|
||||
self.window.set_child(Some(&self.progress));
|
||||
self.window.set_deletable(false);
|
||||
self.window.set_position(WindowPosition::CenterOnParent);
|
||||
self.window.set_modal(true);
|
||||
self.window.resize(200, 50);
|
||||
self.window.set_default_size(200, 50);
|
||||
self
|
||||
}
|
||||
|
||||
@ -59,7 +57,6 @@ impl ProgressWidget {
|
||||
pub fn show(&self) {
|
||||
self.progress.set_fraction(0.0);
|
||||
self.window.show();
|
||||
self.window.show_all();
|
||||
}
|
||||
|
||||
pub fn hide(&self) {
|
||||
@ -92,7 +89,7 @@ trait GnomeScreencast {
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Ffmpeg {
|
||||
pub filename: (FileChooser, Entry, ComboBoxText),
|
||||
pub filename: (File, Entry, ComboBoxText),
|
||||
pub record_video: CheckButton,
|
||||
pub record_audio: CheckButton,
|
||||
pub audio_id: ComboBoxText,
|
||||
@ -123,16 +120,16 @@ impl Ffmpeg {
|
||||
self.saved_filename = Some(
|
||||
self.filename
|
||||
.0
|
||||
.get_filename()
|
||||
.path()
|
||||
.unwrap()
|
||||
.join(PathBuf::from(format!(
|
||||
"{}.{}",
|
||||
if self.filename.1.get_text().to_string().trim().eq("") {
|
||||
if self.filename.1.text().to_string().trim().eq("") {
|
||||
Utc::now().to_string().replace(" UTC", "").replace(" ", "-")
|
||||
} else {
|
||||
self.filename.1.get_text().to_string().trim().to_string()
|
||||
self.filename.1.text().to_string().trim().to_string()
|
||||
},
|
||||
self.filename.2.get_active_id().unwrap().to_string()
|
||||
self.filename.2.active_id().unwrap().to_string()
|
||||
)))
|
||||
.as_path()
|
||||
.display()
|
||||
@ -152,19 +149,22 @@ impl Ffmpeg {
|
||||
&gettext("Would you like to overwrite this file?"),
|
||||
);
|
||||
|
||||
if message_dialog.run() != ResponseType::Ok {
|
||||
message_dialog.connect_response(glib::clone!(@strong message_dialog => move |_, response| {
|
||||
message_dialog.show();
|
||||
if response != ResponseType::Ok {
|
||||
message_dialog.hide();
|
||||
return (None, None);
|
||||
return;
|
||||
}
|
||||
message_dialog.hide();
|
||||
}));
|
||||
}
|
||||
|
||||
if self.record_audio.get_active() {
|
||||
if self.record_audio.is_active() {
|
||||
let mut ffmpeg_command = Command::new("ffmpeg");
|
||||
ffmpeg_command.arg("-f");
|
||||
ffmpeg_command.arg("pulse");
|
||||
ffmpeg_command.arg("-i");
|
||||
ffmpeg_command.arg(self.audio_id.get_active_id().unwrap().to_string());
|
||||
ffmpeg_command.arg(self.audio_id.active_id().unwrap().to_string());
|
||||
ffmpeg_command.arg("-f");
|
||||
ffmpeg_command.arg("ogg");
|
||||
ffmpeg_command.arg(format!(
|
||||
@ -176,7 +176,7 @@ impl Ffmpeg {
|
||||
}
|
||||
|
||||
if is_wayland() {
|
||||
if self.record_video.get_active() {
|
||||
if self.record_video.is_active() {
|
||||
if self.unbound.is_some() {
|
||||
self.clone()
|
||||
.unbound
|
||||
@ -196,14 +196,14 @@ impl Ffmpeg {
|
||||
return (None, self.audio_process_id);
|
||||
}
|
||||
|
||||
if self.record_video.get_active() {
|
||||
if self.record_video.is_active() {
|
||||
let mut ffmpeg_command: Command = Command::new("ffmpeg");
|
||||
|
||||
// record video with specified width and hight
|
||||
ffmpeg_command.arg("-video_size");
|
||||
ffmpeg_command.arg(format!("{}x{}", width, height));
|
||||
ffmpeg_command.arg("-framerate");
|
||||
ffmpeg_command.arg(format!("{}", self.record_frames.get_value()));
|
||||
ffmpeg_command.arg(format!("{}", self.record_frames.value()));
|
||||
ffmpeg_command.arg("-f");
|
||||
ffmpeg_command.arg("x11grab");
|
||||
ffmpeg_command.arg("-i");
|
||||
@ -218,14 +218,14 @@ impl Ffmpeg {
|
||||
|
||||
// if show mouse switch is enabled, draw the mouse to video
|
||||
ffmpeg_command.arg("-draw_mouse");
|
||||
if self.record_mouse.get_active() {
|
||||
if self.record_mouse.is_active() {
|
||||
ffmpeg_command.arg("1");
|
||||
} else {
|
||||
ffmpeg_command.arg("0");
|
||||
}
|
||||
|
||||
// if follow mouse switch is enabled, follow the mouse
|
||||
if self.follow_mouse.get_active() {
|
||||
if self.follow_mouse.is_active() {
|
||||
ffmpeg_command.arg("-follow_mouse");
|
||||
ffmpeg_command.arg("centered");
|
||||
}
|
||||
@ -234,7 +234,7 @@ impl Ffmpeg {
|
||||
ffmpeg_command.arg(self.saved_filename.as_ref().unwrap().to_string());
|
||||
ffmpeg_command.arg("-y");
|
||||
// sleep for delay
|
||||
sleep(Duration::from_secs(self.record_delay.get_value() as u64));
|
||||
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);
|
||||
@ -316,7 +316,7 @@ impl Ffmpeg {
|
||||
if is_audio_record {
|
||||
format!(
|
||||
".temp.without.audio.{}",
|
||||
self.filename.2.get_active_id().unwrap().to_string()
|
||||
self.filename.2.active_id().unwrap().to_string()
|
||||
)
|
||||
} else {
|
||||
"".to_string()
|
||||
@ -343,7 +343,7 @@ impl Ffmpeg {
|
||||
if is_audio_record {
|
||||
format!(
|
||||
".temp.without.audio.{}",
|
||||
self.filename.2.get_active_id().unwrap().to_string()
|
||||
self.filename.2.active_id().unwrap().to_string()
|
||||
)
|
||||
} else {
|
||||
"".to_string()
|
||||
@ -362,7 +362,7 @@ impl Ffmpeg {
|
||||
ffmpeg_audio_merge_command.arg(format!(
|
||||
"{}.temp.without.audio.{}",
|
||||
self.saved_filename.as_ref().unwrap(),
|
||||
self.filename.2.get_active_id().unwrap().to_string()
|
||||
self.filename.2.active_id().unwrap().to_string()
|
||||
));
|
||||
ffmpeg_audio_merge_command.arg("-i");
|
||||
ffmpeg_audio_merge_command.arg(format!(
|
||||
@ -385,7 +385,7 @@ impl Ffmpeg {
|
||||
std::fs::remove_file(format!(
|
||||
"{}.temp.without.audio.{}",
|
||||
self.saved_filename.as_ref().unwrap(),
|
||||
self.filename.2.get_active_id().unwrap().to_string()
|
||||
self.filename.2.active_id().unwrap().to_string()
|
||||
))
|
||||
.unwrap();
|
||||
}
|
||||
@ -415,13 +415,13 @@ impl Ffmpeg {
|
||||
}
|
||||
|
||||
// execute command after finish recording
|
||||
if !(self.command.get_text().trim() == "") {
|
||||
if !(self.command.text().trim() == "") {
|
||||
&self.progress_widget.set_progress(
|
||||
"execute custom command after finish".to_string(),
|
||||
5,
|
||||
6,
|
||||
);
|
||||
Exec::shell(self.command.get_text().trim()).popen().unwrap();
|
||||
Exec::shell(self.command.text().trim()).popen().unwrap();
|
||||
}
|
||||
|
||||
&self
|
||||
@ -438,8 +438,8 @@ impl Ffmpeg {
|
||||
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.get_value()));
|
||||
screencast_options.insert("draw-cursor", Value::new(self.record_mouse.get_active()));
|
||||
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();
|
||||
|
268
src/main.rs
268
src/main.rs
@ -1,25 +1,16 @@
|
||||
extern crate gdk;
|
||||
extern crate gdk_pixbuf;
|
||||
extern crate gettextrs;
|
||||
extern crate gio;
|
||||
extern crate gdk;
|
||||
extern crate gettextrs;
|
||||
extern crate gtk;
|
||||
extern crate libappindicator;
|
||||
mod area_capture;
|
||||
mod config_management;
|
||||
mod ffmpeg_interface;
|
||||
|
||||
// use gio::prelude::*;
|
||||
use ffmpeg_interface::{Ffmpeg, ProgressWidget};
|
||||
use gdk_pixbuf::Pixbuf;
|
||||
use gettextrs::{bindtextdomain, gettext, setlocale, textdomain, LocaleCategory};
|
||||
use glib::signal::Inhibit;
|
||||
use gtk::prelude::*;
|
||||
use gtk::ComboBoxText;
|
||||
use gtk::{
|
||||
AboutDialog, Builder, Button, CheckButton, CssProvider, Entry, FileChooser, Label, MenuItem,
|
||||
SpinButton, Window,
|
||||
};
|
||||
use libappindicator::{AppIndicator, AppIndicatorStatus};
|
||||
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 std::cell::RefCell;
|
||||
use std::ops::Add;
|
||||
use std::path::Path;
|
||||
@ -27,16 +18,24 @@ use std::process::{Command, Stdio};
|
||||
use std::rc::Rc;
|
||||
|
||||
fn main() {
|
||||
//create new application
|
||||
let application = Application::new(Some("sa.sy.blue-recorder"), Default::default(),);
|
||||
application.connect_activate(build_ui);
|
||||
application.run();
|
||||
}
|
||||
|
||||
pub fn build_ui(application: &Application) {
|
||||
// use "GDK_BACKEND=x11" to make xwininfo work in Wayland by using XWayland
|
||||
std::env::set_var("GDK_BACKEND", "x11");
|
||||
if gtk::init().is_err() {
|
||||
println!("Failed to initialize GTK.");
|
||||
return;
|
||||
}
|
||||
|
||||
let ui_src = include_str!("../interfaces/main.ui").to_string();
|
||||
let builder: Builder = Builder::from_string(ui_src.as_str());
|
||||
|
||||
// translate
|
||||
// translate
|
||||
let mut po_path_abs = {
|
||||
let mut current_exec_dir = std::env::current_exe().unwrap();
|
||||
current_exec_dir.pop();
|
||||
@ -59,41 +58,44 @@ fn main() {
|
||||
config_management::initialize();
|
||||
|
||||
// get Objects from UI
|
||||
let main_window: Window = builder.get_object("main_window").unwrap();
|
||||
let about_dialog: AboutDialog = builder.get_object("about_dialog").unwrap();
|
||||
let area_chooser_window: Window = builder.get_object("area_chooser_window").unwrap();
|
||||
let folder_chooser: FileChooser = builder.get_object("filechooser").unwrap();
|
||||
let filename_entry: Entry = builder.get_object("filename").unwrap();
|
||||
let command_entry: Entry = builder.get_object("command").unwrap();
|
||||
let format_chooser_combobox: ComboBoxText = builder.get_object("comboboxtext1").unwrap();
|
||||
let audio_source_combobox: ComboBoxText = builder.get_object("audiosource").unwrap();
|
||||
let record_button: Button = builder.get_object("recordbutton").unwrap();
|
||||
let stop_button: Button = builder.get_object("stopbutton").unwrap();
|
||||
let play_button: Button = builder.get_object("playbutton").unwrap();
|
||||
let window_grab_button: Button = builder.get_object("window_grab_button").unwrap();
|
||||
let area_grab_button: Button = builder.get_object("area_grab_button").unwrap();
|
||||
let area_set_button: Button = builder.get_object("area_set_button").unwrap();
|
||||
let frames_label: Label = builder.get_object("frames_label").unwrap();
|
||||
let delay_label: Label = builder.get_object("delay_label").unwrap();
|
||||
let command_label: Label = builder.get_object("command_label").unwrap();
|
||||
let frames_spin: SpinButton = builder.get_object("frames").unwrap();
|
||||
let delay_spin: SpinButton = builder.get_object("delay").unwrap();
|
||||
let audio_source_label: Label = builder.get_object("audio_source_label").unwrap();
|
||||
let video_switch: CheckButton = builder.get_object("videoswitch").unwrap();
|
||||
let audio_switch: CheckButton = builder.get_object("audioswitch").unwrap();
|
||||
let mouse_switch: CheckButton = builder.get_object("mouseswitch").unwrap();
|
||||
let follow_mouse_switch: CheckButton = builder.get_object("followmouseswitch").unwrap();
|
||||
let about_menu_item: MenuItem = builder.get_object("about_menu_item").unwrap();
|
||||
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_set_button: Button = builder.object("area_set_button").unwrap();
|
||||
let about_menu_item: Button = builder.object("about_menu_item").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();
|
||||
let audio_switch: CheckButton = builder.object("audioswitch").unwrap();
|
||||
let command_entry: Entry = builder.object("command").unwrap();
|
||||
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 filename_entry: Entry = builder.object("filename").unwrap();
|
||||
let folder_chooser_button: Button = builder.object("folderchooser").unwrap();
|
||||
let folder_chooser_label: Label = builder.object("folderchooserlabel").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 record_button: Button = builder.object("recordbutton").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
|
||||
// TODO: add timer
|
||||
|
||||
// --- default properties
|
||||
// Windows
|
||||
main_window.set_title(&gettext("Blue Recorder"));
|
||||
main_window.set_title(Some(&gettext("Blue Recorder")));
|
||||
main_window.set_application(Some(application));
|
||||
// TODO: make area chooser window transparent
|
||||
// NOTICE: it work as snap package
|
||||
area_chooser_window.set_title(&gettext("Area Chooser"));
|
||||
area_chooser_window.set_visual(Some(
|
||||
&gdk::Screen::get_rgba_visual(&gdk::Screen::get_default().unwrap()).unwrap(),
|
||||
));
|
||||
area_chooser_window.set_title(Some(&gettext("Area Chooser")));
|
||||
|
||||
//hide stop & play buttons
|
||||
stop_button.hide();
|
||||
play_button.hide();
|
||||
|
||||
@ -114,6 +116,7 @@ fn main() {
|
||||
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> = {
|
||||
@ -158,10 +161,10 @@ fn main() {
|
||||
audio_source_combobox.set_active(Some(0));
|
||||
|
||||
// Switchs
|
||||
video_switch.set_label(&gettext("Record Video"));
|
||||
audio_switch.set_label(&gettext("Record Audio"));
|
||||
mouse_switch.set_label(&gettext("Show Mouse"));
|
||||
follow_mouse_switch.set_label(&gettext("Follow Mouse"));
|
||||
video_switch.set_label(Some(&gettext("Record Video")));
|
||||
audio_switch.set_label(Some(&gettext("Record Audio")));
|
||||
mouse_switch.set_label(Some(&gettext("Show Mouse")));
|
||||
follow_mouse_switch.set_label(Some(&gettext("Follow Mouse")));
|
||||
video_switch.set_active(config_management::get_bool("default", "videocheck"));
|
||||
audio_switch.set_active(config_management::get_bool("default", "audiocheck"));
|
||||
mouse_switch.set_active(config_management::get_bool("default", "mousecheck"));
|
||||
@ -170,8 +173,8 @@ fn main() {
|
||||
let _mouse_switch = mouse_switch.clone();
|
||||
let _follow_mouse_switch = follow_mouse_switch.clone();
|
||||
video_switch.connect_toggled(move |switch: &CheckButton| {
|
||||
config_management::set_bool("default", "videocheck", switch.get_active());
|
||||
if switch.get_active() {
|
||||
config_management::set_bool("default", "videocheck", switch.is_active());
|
||||
if switch.is_active() {
|
||||
_mouse_switch.set_sensitive(true);
|
||||
_follow_mouse_switch.set_sensitive(true);
|
||||
} else {
|
||||
@ -181,18 +184,18 @@ fn main() {
|
||||
});
|
||||
let _follow_mouse_switch = follow_mouse_switch.clone();
|
||||
mouse_switch.connect_toggled(move |switch: &CheckButton| {
|
||||
config_management::set_bool("default", "mousecheck", switch.get_active());
|
||||
if switch.get_active() {
|
||||
config_management::set_bool("default", "mousecheck", switch.is_active());
|
||||
if switch.is_active() {
|
||||
_follow_mouse_switch.set_sensitive(true);
|
||||
} else {
|
||||
_follow_mouse_switch.set_sensitive(false);
|
||||
}
|
||||
});
|
||||
audio_switch.connect_toggled(|switch: &CheckButton| {
|
||||
config_management::set_bool("default", "audiocheck", switch.get_active());
|
||||
config_management::set_bool("default", "audiocheck", switch.is_active());
|
||||
});
|
||||
follow_mouse_switch.connect_toggled(|switch: &CheckButton| {
|
||||
config_management::set_bool("default", "followmousecheck", switch.get_active());
|
||||
config_management::set_bool("default", "followmousecheck", switch.is_active());
|
||||
});
|
||||
|
||||
// Buttons
|
||||
@ -223,7 +226,7 @@ fn main() {
|
||||
config_management::set(
|
||||
"default",
|
||||
"frame",
|
||||
_frames_spin.get_value().to_string().as_str(),
|
||||
_frames_spin.value().to_string().as_str(),
|
||||
);
|
||||
});
|
||||
let _delay_spin = delay_spin.to_owned();
|
||||
@ -231,19 +234,42 @@ fn main() {
|
||||
config_management::set(
|
||||
"default",
|
||||
"delay",
|
||||
_delay_spin.get_value().to_string().as_str(),
|
||||
_delay_spin.value().to_string().as_str(),
|
||||
);
|
||||
});
|
||||
|
||||
// Other
|
||||
folder_chooser.set_uri(&config_management::get("default", "folder"));
|
||||
// FileChooser
|
||||
let folder_chooser_native = FileChooserNative::new(
|
||||
Some("Select Folder"),
|
||||
Some(&main_window),
|
||||
FileChooserAction::SelectFolder,
|
||||
Some("Select"),
|
||||
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();
|
||||
folder_chooser_label.set_label(&folder_chooser_name.to_string_lossy());
|
||||
// show file chooser dialog
|
||||
folder_chooser_button.connect_clicked(glib::clone!(@strong folder_chooser_native => move |_| {
|
||||
folder_chooser_native.connect_response(glib::clone!(@strong folder_chooser_native, @strong folder_chooser_label => move |_, response| {
|
||||
if response == gtk::ResponseType::Accept {
|
||||
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());
|
||||
// TODO: change folder icon
|
||||
};
|
||||
folder_chooser_native.destroy();
|
||||
}));
|
||||
folder_chooser_native.show();
|
||||
}));
|
||||
|
||||
// --- 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_activate(move |_| {
|
||||
_about_dialog.run();
|
||||
_about_dialog.hide();
|
||||
about_menu_item.connect_clicked(move |_| {
|
||||
_about_dialog.show();
|
||||
_about_dialog.set_hide_on_close(true);
|
||||
});
|
||||
|
||||
// Buttons
|
||||
@ -304,39 +330,39 @@ fn main() {
|
||||
.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::Menu::new();
|
||||
let indicator_stop_recording = gtk::MenuItem::with_label(&gettext("stop recording"));
|
||||
menu.append(&indicator_stop_recording);
|
||||
menu.show_all();
|
||||
indicator.clone().borrow_mut().set_menu(&mut menu);
|
||||
//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(move |_| {
|
||||
_ffmpeg_record_interface.borrow_mut().clone().stop_record();
|
||||
_indicator
|
||||
.borrow_mut()
|
||||
.set_status(AppIndicatorStatus::Passive);
|
||||
//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();
|
||||
});
|
||||
//_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 mut _indicator = indicator.clone();
|
||||
let _stop_button = stop_button.clone();
|
||||
let _record_button = record_button.clone();
|
||||
record_button.connect_clicked(move |_| {
|
||||
@ -351,10 +377,10 @@ fn main() {
|
||||
// do nothing if the start_record function return nothing
|
||||
}
|
||||
_ => {
|
||||
_indicator
|
||||
.borrow_mut()
|
||||
.set_status(AppIndicatorStatus::Active);
|
||||
|
||||
//_indicator
|
||||
//.borrow_mut()
|
||||
//.set_status(AppIndicatorStatus::Active);
|
||||
|
||||
_record_button.hide();
|
||||
_stop_button.show();
|
||||
}
|
||||
@ -362,15 +388,15 @@ fn main() {
|
||||
});
|
||||
|
||||
let mut _ffmpeg_record_interface = ffmpeg_record_interface.clone();
|
||||
let mut _indicator = indicator.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 |_| {
|
||||
_ffmpeg_record_interface.borrow_mut().clone().stop_record();
|
||||
_indicator
|
||||
.borrow_mut()
|
||||
.set_status(AppIndicatorStatus::Passive);
|
||||
//_indicator
|
||||
//.borrow_mut()
|
||||
//.set_status(AppIndicatorStatus::Passive);
|
||||
|
||||
_record_button.show();
|
||||
_stop_button.hide();
|
||||
@ -383,61 +409,59 @@ fn main() {
|
||||
});
|
||||
|
||||
// About Dialog
|
||||
about_menu_item.set_label("about");
|
||||
let logo = Image::from_file(&indicator_icon_path.to_str().unwrap());
|
||||
about_dialog.set_transient_for(Some(&main_window));
|
||||
about_dialog.set_program_name(&gettext("Blue Recorder"));
|
||||
about_dialog.set_version(Some("0.1.5"));
|
||||
about_dialog.set_program_name(Some(&gettext("Blue Recorder")));
|
||||
about_dialog.set_version(Some("0.2.0"));
|
||||
about_dialog.set_copyright(Some("© 2021 Salem Yaslem"));
|
||||
about_dialog.set_wrap_license(true);
|
||||
about_dialog.set_license(Some("Blue Recorder is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nBlue Recorder is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\nSee the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Blue Recorder. If not, see <http://www.gnu.org/licenses/>."));
|
||||
about_dialog.set_comments(Some(&gettext(
|
||||
"A simple screen recorder for Linux desktop. Supports Wayland & Xorg.",
|
||||
"A simple screen recorder for Linux desktop. Supports Waylan_windowd & Xorg.",
|
||||
)));
|
||||
about_dialog.set_authors(&[
|
||||
"Salem Yaslem <s@sy.sa>",
|
||||
"M.Hanny Sabbagh <mhsabbagh@outlook.com>",
|
||||
"Alessandro Toia <gort818@gmail.com>",
|
||||
"Suliman Altassan <suliman@dismail.de>",
|
||||
"O.Chibani <11yzyv86j@relay.firefox.com>",
|
||||
"Patreon Supporters: Ahmad Gharib, Medium,\nWilliam Grunow, Alex Benishek.",
|
||||
]);
|
||||
about_dialog.set_artists(&["Mustapha Assabar", "Abdullah Al-Baroty <albaroty@gmail.com>"]);
|
||||
about_dialog.set_website(Some("https://github.com/xlmnxp/blue-recorder/"));
|
||||
about_dialog.set_logo_icon_name(Some("blue-recorder"));
|
||||
about_dialog.set_logo(Some(
|
||||
&Pixbuf::from_file(&indicator_icon_path.to_str().unwrap()).unwrap(),
|
||||
));
|
||||
about_dialog.set_transient_for(Some(&main_window));
|
||||
about_dialog.set_logo(logo.paintable().as_ref());
|
||||
about_dialog.set_modal(true);
|
||||
|
||||
// Windows
|
||||
// hide area chooser after it deleted.
|
||||
let _area_chooser_window = area_chooser_window.clone();
|
||||
area_chooser_window.connect_delete_event(move |_, _event: &gdk::Event| {
|
||||
area_chooser_window.connect_close_request (move |_| {
|
||||
_area_chooser_window.hide();
|
||||
Inhibit(true)
|
||||
gtk::Inhibit(true)
|
||||
});
|
||||
|
||||
// close the application when main window destroy
|
||||
// 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 |_| {
|
||||
// stop recording before close the application
|
||||
//let mut _indicator = indicator.clone();
|
||||
main_window.connect_destroy(move |main_window| {
|
||||
// stop recording before close the application
|
||||
_ffmpeg_record_interface.borrow_mut().clone().stop_record();
|
||||
_indicator
|
||||
.borrow_mut()
|
||||
.set_status(AppIndicatorStatus::Passive);
|
||||
gtk::main_quit();
|
||||
//_indicator
|
||||
//.borrow_mut()
|
||||
//.set_status(AppIndicatorStatus::Passive);
|
||||
main_window.close();
|
||||
});
|
||||
|
||||
// apply css
|
||||
let provider = CssProvider::new();
|
||||
provider
|
||||
.load_from_data(include_str!("styles/global.css").as_bytes())
|
||||
.unwrap();
|
||||
gtk::StyleContext::add_provider_for_screen(
|
||||
&gdk::Screen::get_default().unwrap(),
|
||||
.load_from_data(include_str!("styles/global.css").as_bytes());
|
||||
gtk::StyleContext::add_provider_for_display(
|
||||
&area_chooser_window.display(),
|
||||
&provider,
|
||||
gtk::STYLE_PROVIDER_PRIORITY_APPLICATION,
|
||||
);
|
||||
|
||||
gtk::main();
|
||||
main_window.show();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user