Initial gtk4 migration

This commit is contained in:
ochibani 2022-09-25 01:45:15 +02:00
parent 9b4ec9bb05
commit 6f48df3a6a
7 changed files with 1606 additions and 1175 deletions

1251
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -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"

File diff suppressed because it is too large Load Diff

143
po/tr.po
View File

@ -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
View 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)

View File

@ -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();

View File

@ -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();
}