Merge pull request #14 from ochibani/restore-wayland-support

read wayland stream width and height
This commit is contained in:
Chibani 2025-01-23 06:38:44 +02:00 committed by GitHub
commit 9c4d8c6b82
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 618 additions and 16 deletions

270
Cargo.lock generated
View File

@ -496,10 +496,12 @@ dependencies = [
"chrono",
"ffmpeg-sidecar",
"glib 0.10.3",
"gstreamer",
"libadwaita",
"open",
"subprocess",
"tempfile",
"zbus 5.3.0",
]
[[package]]
@ -620,6 +622,16 @@ dependencies = [
"target-lexicon",
]
[[package]]
name = "cfg-expr"
version = "0.17.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d4ba6e40bd1184518716a6e1a781bf9160e286d219ccdb8ab2612e74cfe4789"
dependencies = [
"smallvec",
"target-lexicon",
]
[[package]]
name = "cfg-if"
version = "0.1.10"
@ -1486,7 +1498,7 @@ version = "0.16.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3092cf797a5f1210479ea38070d9ae8a5b8e9f8f1be9f32f4643c529c7d70016"
dependencies = [
"gio-sys",
"gio-sys 0.16.3",
"glib-sys 0.16.3",
"gobject-sys 0.16.3",
"libc",
@ -1517,7 +1529,7 @@ checksum = "de55cb49432901fe2b3534177fa06844665b9b0911d85d8601a8d8b88b7791db"
dependencies = [
"cairo-sys-rs",
"gdk-pixbuf-sys",
"gio-sys",
"gio-sys 0.16.3",
"glib-sys 0.16.3",
"gobject-sys 0.16.3",
"libc",
@ -1568,7 +1580,7 @@ dependencies = [
"futures-core",
"futures-io",
"futures-util",
"gio-sys",
"gio-sys 0.16.3",
"glib 0.16.9",
"libc",
"once_cell",
@ -1590,6 +1602,19 @@ dependencies = [
"winapi",
]
[[package]]
name = "gio-sys"
version = "0.20.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8446d9b475730ebef81802c1738d972db42fde1c5a36a627ebc4d665fc87db04"
dependencies = [
"glib-sys 0.20.7",
"gobject-sys 0.20.7",
"libc",
"system-deps 7.0.3",
"windows-sys 0.59.0",
]
[[package]]
name = "glib"
version = "0.10.3"
@ -1621,7 +1646,7 @@ dependencies = [
"futures-executor",
"futures-task",
"futures-util",
"gio-sys",
"gio-sys 0.16.3",
"glib-macros 0.16.8",
"glib-sys 0.16.3",
"gobject-sys 0.16.3",
@ -1631,6 +1656,27 @@ dependencies = [
"thiserror 1.0.69",
]
[[package]]
name = "glib"
version = "0.20.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f969edf089188d821a30cde713b6f9eb08b20c63fc2e584aba2892a7984a8cc0"
dependencies = [
"bitflags 2.8.0",
"futures-channel",
"futures-core",
"futures-executor",
"futures-task",
"futures-util",
"gio-sys 0.20.8",
"glib-macros 0.20.7",
"glib-sys 0.20.7",
"gobject-sys 0.20.7",
"libc",
"memchr",
"smallvec",
]
[[package]]
name = "glib-macros"
version = "0.10.1"
@ -1662,6 +1708,19 @@ dependencies = [
"syn 1.0.109",
]
[[package]]
name = "glib-macros"
version = "0.20.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "715601f8f02e71baef9c1f94a657a9a77c192aea6097cf9ae7e5e177cd8cde68"
dependencies = [
"heck 0.5.0",
"proc-macro-crate 3.2.0",
"proc-macro2",
"quote",
"syn 2.0.96",
]
[[package]]
name = "glib-sys"
version = "0.10.1"
@ -1682,6 +1741,16 @@ dependencies = [
"system-deps 6.2.2",
]
[[package]]
name = "glib-sys"
version = "0.20.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b360ff0f90d71de99095f79c526a5888c9c92fc9ee1b19da06c6f5e75f0c2a53"
dependencies = [
"libc",
"system-deps 7.0.3",
]
[[package]]
name = "glob"
version = "0.3.2"
@ -1722,6 +1791,17 @@ dependencies = [
"system-deps 6.2.2",
]
[[package]]
name = "gobject-sys"
version = "0.20.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67a56235e971a63bfd75abb13ef70064e1346388723422a68580d8a6fbac6423"
dependencies = [
"glib-sys 0.20.7",
"libc",
"system-deps 7.0.3",
]
[[package]]
name = "graphene-rs"
version = "0.16.3"
@ -1777,6 +1857,43 @@ dependencies = [
"system-deps 6.2.2",
]
[[package]]
name = "gstreamer"
version = "0.23.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "700cb1b2e86dda424f85eb728102a111602317e40b4dd71cf1c0dc04e0cc5d95"
dependencies = [
"cfg-if 1.0.0",
"futures-channel",
"futures-core",
"futures-util",
"glib 0.20.7",
"gstreamer-sys",
"itertools 0.13.0",
"libc",
"muldiv",
"num-integer",
"num-rational",
"once_cell",
"option-operations",
"paste",
"pin-project-lite",
"smallvec",
"thiserror 2.0.11",
]
[[package]]
name = "gstreamer-sys"
version = "0.23.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16cf1ae0a869aa7066ce3c685b76053b4b4f48f364a5b18c4b1f36ef57469719"
dependencies = [
"glib-sys 0.20.7",
"gobject-sys 0.20.7",
"libc",
"system-deps 7.0.3",
]
[[package]]
name = "gtk4"
version = "0.5.5"
@ -1823,7 +1940,7 @@ dependencies = [
"cairo-sys-rs",
"gdk-pixbuf-sys",
"gdk4-sys",
"gio-sys",
"gio-sys 0.16.3",
"glib-sys 0.16.3",
"gobject-sys 0.16.3",
"graphene-sys",
@ -2325,7 +2442,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de902982372b454a0081d7fd9dd567b37b73ae29c8f6da1820374d345fd95d5b"
dependencies = [
"gdk4-sys",
"gio-sys",
"gio-sys 0.16.3",
"glib-sys 0.16.3",
"gobject-sys 0.16.3",
"gtk4-sys",
@ -2511,6 +2628,12 @@ dependencies = [
"simd-adler32",
]
[[package]]
name = "muldiv"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "956787520e75e9bd233246045d19f42fb73242759cc57fba9611d940ae96d4b0"
[[package]]
name = "nb-connect"
version = "1.2.0"
@ -2724,6 +2847,15 @@ dependencies = [
"pathdiff",
]
[[package]]
name = "option-operations"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c26d27bb1aeab65138e4bf7666045169d1717febcc9ff870166be8348b223d0"
dependencies = [
"paste",
]
[[package]]
name = "ordered-multimap"
version = "0.3.1"
@ -3589,7 +3721,20 @@ version = "6.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349"
dependencies = [
"cfg-expr",
"cfg-expr 0.15.8",
"heck 0.5.0",
"pkg-config",
"toml 0.8.19",
"version-compare 0.2.0",
]
[[package]]
name = "system-deps"
version = "7.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "66d23aaf9f331227789a99e8de4c91bf46703add012bdfd45fdecdfb2975a005"
dependencies = [
"cfg-expr 0.17.2",
"heck 0.5.0",
"pkg-config",
"toml 0.8.19",
@ -4734,10 +4879,46 @@ dependencies = [
"windows-sys 0.52.0",
"xdg-home",
"zbus_macros 4.4.0",
"zbus_names",
"zbus_names 3.0.0",
"zvariant 4.2.0",
]
[[package]]
name = "zbus"
version = "5.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "192a0d989036cd60a1e91a54c9851fb9ad5bd96125d41803eed79d2e2ef74bd7"
dependencies = [
"async-broadcast",
"async-executor",
"async-fs",
"async-io 2.4.0",
"async-lock 3.4.0",
"async-process",
"async-recursion",
"async-task",
"async-trait",
"blocking",
"enumflags2 0.7.11",
"event-listener 5.4.0",
"futures-core",
"futures-util",
"hex",
"nix 0.29.0",
"ordered-stream",
"serde",
"serde_repr",
"static_assertions",
"tracing",
"uds_windows",
"windows-sys 0.59.0",
"winnow 0.6.24",
"xdg-home",
"zbus_macros 5.3.0",
"zbus_names 4.1.1",
"zvariant 5.2.0",
]
[[package]]
name = "zbus_macros"
version = "1.9.3"
@ -4760,7 +4941,22 @@ dependencies = [
"proc-macro2",
"quote",
"syn 2.0.96",
"zvariant_utils",
"zvariant_utils 2.1.0",
]
[[package]]
name = "zbus_macros"
version = "5.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3685b5c81fce630efc3e143a4ded235b107f1b1cdf186c3f115529e5e5ae4265"
dependencies = [
"proc-macro-crate 3.2.0",
"proc-macro2",
"quote",
"syn 2.0.96",
"zbus_names 4.1.1",
"zvariant 5.2.0",
"zvariant_utils 3.1.0",
]
[[package]]
@ -4774,6 +4970,18 @@ dependencies = [
"zvariant 4.2.0",
]
[[package]]
name = "zbus_names"
version = "4.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "519629a3f80976d89c575895b05677cbc45eaf9f70d62a364d819ba646409cc8"
dependencies = [
"serde",
"static_assertions",
"winnow 0.6.24",
"zvariant 5.2.0",
]
[[package]]
name = "zerocopy"
version = "0.7.35"
@ -4980,6 +5188,21 @@ dependencies = [
"zvariant_derive 4.2.0",
]
[[package]]
name = "zvariant"
version = "5.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55e6b9b5f1361de2d5e7d9fd1ee5f6f7fcb6060618a1f82f3472f58f2b8d4be9"
dependencies = [
"endi",
"enumflags2 0.7.11",
"serde",
"static_assertions",
"winnow 0.6.24",
"zvariant_derive 5.2.0",
"zvariant_utils 3.1.0",
]
[[package]]
name = "zvariant_derive"
version = "2.10.0"
@ -5002,7 +5225,20 @@ dependencies = [
"proc-macro2",
"quote",
"syn 2.0.96",
"zvariant_utils",
"zvariant_utils 2.1.0",
]
[[package]]
name = "zvariant_derive"
version = "5.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "573a8dd76961957108b10f7a45bac6ab1ea3e9b7fe01aff88325dc57bb8f5c8b"
dependencies = [
"proc-macro-crate 3.2.0",
"proc-macro2",
"quote",
"syn 2.0.96",
"zvariant_utils 3.1.0",
]
[[package]]
@ -5015,3 +5251,17 @@ dependencies = [
"quote",
"syn 2.0.96",
]
[[package]]
name = "zvariant_utils"
version = "3.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddd46446ea2a1f353bfda53e35f17633afa79f4fe290a611c94645c69fe96a50"
dependencies = [
"proc-macro2",
"quote",
"serde",
"static_assertions",
"syn 2.0.96",
"winnow 0.6.24",
]

View File

@ -14,6 +14,8 @@ async-std = {version = "1.12.0", features = ["attributes"]}
chrono = { version = "0.4.19", optional = true }
ffmpeg-sidecar = "2.0.5"
glib = { version = "0.10.3", optional = true }
gstreamer = "0.23.4"
open = "5.1.4"
subprocess = {version = "0.2.6", optional = true }
tempfile = "3.10.1"
zbus = "5.3.0"

View File

@ -3,6 +3,7 @@ use adw::gtk::{CheckButton, ComboBoxText, Entry, FileChooserNative, SpinButton};
#[cfg(feature = "gtk")]
use adw::gtk::prelude::*;
use anyhow::{anyhow, Error, Result};
use chrono::Timelike;
#[cfg(feature = "gtk")]
use chrono::Utc;
use ffmpeg_sidecar::child::FfmpegChild;
@ -18,11 +19,12 @@ use std::time::Duration;
#[cfg(feature = "cmd")]
use std::time::Instant;
use crate::utils::{is_video_record, RecordMode};
use crate::utils::{is_video_record, is_wayland, RecordMode};
#[cfg(feature = "cmd")]
use crate::utils::{is_input_audio_record, is_output_audio_record, is_valid};
#[cfg(feature = "gtk")]
use crate::utils::validate_video_file;
use crate::wayland_linux::{CursorModeTypes, RecordTypes, WaylandRecorder};
#[cfg(feature = "cmd")]
#[derive(Clone)]
@ -56,6 +58,7 @@ pub struct Ffmpeg {
pub output: String,
pub temp_video_filename: String,
pub saved_filename: String,
pub width: Option<u16>,
pub height: Option<u16>,
pub input_audio_process: Option<Rc<RefCell<FfmpegChild>>>,
pub output_audio_process: Option<Rc<RefCell<FfmpegChild>>>,
@ -70,6 +73,7 @@ pub struct Ffmpeg {
pub record_mouse: CheckButton,
pub show_area: CheckButton,
pub video_switch: CheckButton,
pub wayland_recorder: WaylandRecorder,
}
#[cfg(feature = "cmd")]
@ -87,6 +91,7 @@ impl Ffmpeg {
);
let mut ffmpeg_command = FfmpegCommand::new();
let format = "x11grab";
self.width = Some(width);
self.height = Some(height);
// Record video to tmp if audio record enabled
@ -483,6 +488,35 @@ impl Ffmpeg {
//if mode == RecordMode::Window && !self.follow_mouse.is_active() {
// TODO pulse = gstreamer for video && add to cmd linux + add convert function to gstreamer ouput
//} else {
if is_wayland() {
let folder_path = Path::new(&self.saved_filename)
.parent()
.ok_or_else(|| anyhow!("Failed to get parent path."))?;
self.temp_video_filename = folder_path
.join(format!(".blue-recorder-{}.webm", Utc::now().nanosecond()))
.to_string_lossy()
.to_string();
// Start recording
let stream = glib::MainContext::default().block_on(self.wayland_recorder.start(
self.temp_video_filename.clone(),
match mode {
RecordMode::Screen => RecordTypes::Monitor,
RecordMode::Window => RecordTypes::Window,
_ => RecordTypes::MonitorOrWindow,
},
if self.record_mouse.is_active() {
CursorModeTypes::Show
} else {
CursorModeTypes::Hidden
},
));
self.width = Some(width);
self.height = Some(height);
return Ok(());
}
let display = format!("{}+{},{}",
std::env::var("DISPLAY").unwrap_or_else(|_| ":0".to_string())
.as_str(),
@ -491,6 +525,7 @@ impl Ffmpeg {
);
let mut ffmpeg_command = FfmpegCommand::new();
let format = "x11grab";
self.width = Some(width);
self.height = Some(height);
let filename = self.saved_filename.clone();
self.output = Path::new(&filename).extension()
@ -637,6 +672,17 @@ impl Ffmpeg {
return Err(Error::msg(format!("{}", error)));
},
}
} else if self.video_switch.is_active() && is_wayland() {
glib::MainContext::default().block_on(self.wayland_recorder.stop());
match self.merge() {
Ok(_) => {
self.clean()?;
},
Err(error) => {
self.clean()?;
return Err(Error::msg(format!("{}", error)));
}
}
}
Ok(())
}

View File

@ -1,5 +1,7 @@
pub mod wayland_linux;
pub mod ffmpeg_linux;
pub mod ffmpeg_windows;
pub mod utils;
pub mod utils;

300
core/src/wayland_linux.rs Normal file
View File

@ -0,0 +1,300 @@
use anyhow::{Error, Result};
use gst::prelude::*;
use gstreamer as gst;
use std::collections::HashMap;
use zbus::{
export::futures_util::TryStreamExt,
message, proxy,
zvariant::{Dict, ObjectPath, OwnedObjectPath, Str, Structure, Value},
Connection, MessageStream,
};
#[derive(Clone, Copy)]
pub enum RecordTypes {
Default,
Monitor,
Window,
MonitorOrWindow,
}
#[derive(Clone, Copy)]
pub enum CursorModeTypes {
Default,
Hidden,
Show,
}
#[proxy(
interface = "org.freedesktop.portal.ScreenCast",
default_service = "org.freedesktop.portal.Desktop",
default_path = "/org/freedesktop/portal/desktop"
)]
trait ScreenCast {
async fn create_session(&self, options: HashMap<&str, Value<'_>>) -> Result<OwnedObjectPath>;
async fn select_sources(
&self,
session_handle: ObjectPath<'_>,
options: HashMap<&str, Value<'_>>,
) -> Result<OwnedObjectPath>;
async fn start(
&self,
session_handle: ObjectPath<'_>,
parent_window: &str,
options: HashMap<&str, Value<'_>>,
) -> Result<OwnedObjectPath>;
}
#[derive(Clone)]
pub struct WaylandRecorder {
connection: Connection,
screen_cast_proxy: ScreenCastProxy<'static>,
session_path: String,
pipeline: Option<gst::Pipeline>,
filename: String,
}
impl WaylandRecorder {
pub async fn new() -> Self {
let connection = Connection::session()
.await
.expect("failed to connect to session bus");
let screen_cast_proxy = ScreenCastProxy::new(&connection)
.await
.expect("failed to create dbus proxy for screen-cast");
gst::init().expect("failed to initialize gstreamer");
WaylandRecorder {
connection,
screen_cast_proxy,
session_path: String::new(),
filename: String::from("blue_recorder.webm"),
pipeline: None,
}
}
pub async fn start(
&mut self,
filename: String,
record_type: RecordTypes,
cursor_mode_type: CursorModeTypes,
) -> (i32, i32) {
self.screen_cast_proxy
.create_session(HashMap::from([
("handle_token", Value::from("blue_recorder_1")),
("session_handle_token", Value::from("blue_recorder_1")),
]))
.await
.expect("failed to create session");
let (mut height, mut width) = (0, 0);
let mut message_stream = MessageStream::from(self.connection.clone());
self.filename = filename.clone();
while let Some(msg) = message_stream
.try_next()
.await
.expect("failed to get message")
{
match msg.message_type() {
message::Type::Signal => {
let body = msg.body();
let (response_num, response): (u32, HashMap<&str, Value>) =
body.deserialize().unwrap();
if response_num > 0 {
return (height, width);
}
if response.len() == 0 {
continue;
}
if response.contains_key("session_handle") {
self.handle_session(
self.screen_cast_proxy.clone(),
response.clone(),
record_type,
cursor_mode_type,
)
.await
.expect("failed to handle session");
continue;
}
if response.contains_key("streams") {
let stream = self.record_screen_cast(response.clone())
.await
.expect("failed to record screen cast");
width = stream.0;
height = stream.1;
break;
}
}
_ => {
println!("\n\nUnkown message: {:?}", msg);
}
}
}
(height, width)
}
pub async fn stop(&mut self) {
if let Some(pipeline) = self.pipeline.clone() {
pipeline
.set_state(gst::State::Null)
.expect("failed to stop pipeline");
}
if self.session_path.len() > 0 {
println!(
"Closing session...: {:?}",
self.session_path.replace("request", "session")
);
self.connection
.clone()
.call_method(
Some("org.freedesktop.portal.Desktop"),
self.session_path.clone().replace("request", "session"),
Some("org.freedesktop.portal.Session"),
"Close",
&(),
)
.await
.expect("failed to close session");
self.session_path = String::new();
}
}
async fn handle_session(
&mut self,
screen_cast_proxy: ScreenCastProxy<'_>,
response: HashMap<&str, Value<'_>>,
record_type: RecordTypes,
cursor_mode_type: CursorModeTypes,
) -> Result<()> {
let response_session_handle = response
.get("session_handle")
.expect("cannot get session_handle")
.clone()
.downcast::<String>()
.expect("cannot down cast session_handle");
self.session_path = response_session_handle.clone();
screen_cast_proxy
.select_sources(
ObjectPath::try_from(response_session_handle.clone())?,
HashMap::from([
("handle_token", Value::from("blue_recorder_1")),
(
"types",
Value::from(match record_type {
RecordTypes::Monitor => 1u32,
RecordTypes::Window => 2u32,
RecordTypes::MonitorOrWindow => 3u32,
_ => 0u32,
}),
),
(
"cursor_mode",
Value::from(match cursor_mode_type {
CursorModeTypes::Hidden => 1u32,
CursorModeTypes::Show => 2u32,
_ => 0u32,
}),
),
]),
)
.await?;
screen_cast_proxy
.start(
ObjectPath::try_from(response_session_handle.clone())?,
"parent_window",
HashMap::from([("handle_token", Value::from("blue_recorder_1"))]),
)
.await?;
Ok(())
}
async fn record_screen_cast(&mut self, response: HashMap<&str, Value<'_>>) -> Result<(i32, i32)> {
let streams: &Value<'_> = response.get("streams").expect("cannot get streams");
let (mut width, mut height) = (0, 0);
let stream_fields = streams
.clone()
.downcast::<Vec<Value>>()
.expect("cannot down cast streams to vec array")
.first()
.expect("cannot get first object from streams array")
.clone()
.downcast::<Structure>()
.expect("cannot down cast first object to structure");
if let Some(field) = stream_fields.fields().get(1) {
let dict = field
.clone()
.downcast::<Dict>()
.expect("cannot down cast field to value");
let size_str = Str::from("size");
let size = dict
.get::<Str, Structure>(&size_str)
.expect("cannot get size")
.expect("cannot get size structure");
let fields = size.fields();
let size = fields
.iter()
.map(|field| {
field
.clone()
.downcast::<i32>()
.expect("cannot down cast width to i32")
})
.collect::<Vec<i32>>();
let [stream_width, stream_height] = size.as_slice() else {
return Err(Error::msg("cannot get width and height"));
};
width = *stream_width;
height = *stream_height;
}
// get fields from nested structure inside elements
// NOTICE: this is not the best way to get node_id, but it works for now
let stream_node_id: u32 = stream_fields.fields()
.first()
.expect("cannot get first field from structure")
.clone()
.downcast::<u32>()
.expect("cannot down cast first field to u32");
// launch gstreamer pipeline
let gst_element: gst::Element = gst::parse::launch(&format!(
"pipewiresrc path={stream_node_id} ! videorate ! video/x-raw,framerate=60/1 ! videoconvert ! vp8enc min-quantizer=0 max-quantizer=1 keyframe-mode=disabled buffer-size=20000 ! webmmux ! filesink location={filename}",
filename = self.filename
)).expect("failed to launch gstreamer pipeline");
// start pipeline
let pipeline: gst::Pipeline = gst_element
.dynamic_cast::<gst::Pipeline>()
.expect("pipeline error");
self.pipeline = Some(pipeline.clone());
pipeline
.set_state(gst::State::Playing)
.expect("failed to start pipeline");
println!("Recording Wayland screen cast...");
Ok((width, height))
}
}

View File

@ -12,6 +12,7 @@ use blue_recorder_core::utils::{disable_input_widgets, enable_input_widgets,
is_overwrite, is_wayland, play_record, RecordMode, validate_video_file};
#[cfg(any(target_os = "freebsd", target_os = "linux"))]
use blue_recorder_core::utils::{audio_output_source, sources_descriptions_list};
use blue_recorder_core::wayland_linux::WaylandRecorder;
#[cfg(target_os = "windows")]
use cpal::traits::{DeviceTrait, HostTrait};
use std::cell::RefCell;
@ -791,6 +792,7 @@ fn build_ui(application: &Application, error_dialog: MessageDialog, error_messag
show_area: area_switch,
video_switch: video_switch.clone()
}));
#[cfg(any(target_os = "freebsd", target_os = "linux"))]
let ffmpeg_record_interface: Rc<RefCell<Ffmpeg>> = Rc::new(RefCell::new(Ffmpeg {
audio_input_id: audio_source_combobox.clone(),
@ -803,6 +805,7 @@ fn build_ui(application: &Application, error_dialog: MessageDialog, error_messag
output: String::new(),
temp_video_filename: String::new(),
saved_filename: String::new(),
width: None,
height: None,
input_audio_process: None,
output_audio_process: None,
@ -817,6 +820,7 @@ fn build_ui(application: &Application, error_dialog: MessageDialog, error_messag
record_mouse: mouse_switch.clone(),
show_area: area_switch,
video_switch: video_switch.clone(),
wayland_recorder: glib::MainContext::default().block_on(WaylandRecorder::new())
}));
// Record button
@ -832,8 +836,7 @@ fn build_ui(application: &Application, error_dialog: MessageDialog, error_messag
let _error_dialog = error_dialog.clone();
let _error_message = error_message.clone();
let _follow_mouse_switch = follow_mouse_switch.clone();
let mut _input_widgets = input_widgets.clone();
//let main_context = glib::MainContext::default();
let mut _input_widgets: Vec<Widget> = input_widgets.clone();
let _main_window = main_window.clone();
let _mouse_switch = mouse_switch.clone();
let _play_button = play_button.clone();
@ -841,7 +844,6 @@ fn build_ui(application: &Application, error_dialog: MessageDialog, error_messag
let _record_time_label = record_time_label.clone();
let _stop_button = stop_button.clone();
let _video_switch = video_switch.clone();
//let wayland_record = main_context.block_on(WaylandRecorder::new());
let mut _ffmpeg_record_interface = ffmpeg_record_interface.clone();
let second_click: Rc<RefCell<RecordClick>> = Rc::new(RefCell::new(RecordClick {
is_record_button_clicked: false,
@ -900,7 +902,7 @@ fn build_ui(application: &Application, error_dialog: MessageDialog, error_messag
second_click.clone(),
);
}
} else if _delay_spin.value() as u16 == 0 && !is_wayland() {
} else if _delay_spin.value() as u16 == 0 {
let _area_capture = area_capture.borrow_mut();
disable_input_widgets(_input_widgets.clone());
start_timer(record_time_label.clone());