client: screen relay switched to ximagesink
This commit is contained in:
parent
39e4458967
commit
3aef06001b
@ -23,6 +23,16 @@ fn ensure_runtime_dir() {
|
|||||||
|
|
||||||
#[tokio::main(flavor = "current_thread")]
|
#[tokio::main(flavor = "current_thread")]
|
||||||
async fn main() -> Result<()> {
|
async fn main() -> Result<()> {
|
||||||
|
// Prefer X11/Xwayland on KDE Wayland so wmctrl-based placement works
|
||||||
|
if env::var_os("WAYLAND_DISPLAY").is_some() {
|
||||||
|
if let Some(desktop) = env::var_os("XDG_CURRENT_DESKTOP") {
|
||||||
|
if desktop.to_string_lossy().to_ascii_lowercase().contains("kde") {
|
||||||
|
env::set_var("GDK_BACKEND", "x11");
|
||||||
|
env::set_var("WINIT_UNIX_BACKEND", "x11");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ensure_runtime_dir();
|
ensure_runtime_dir();
|
||||||
|
|
||||||
/*------------- common filter & stderr layer ------------------------*/
|
/*------------- common filter & stderr layer ------------------------*/
|
||||||
|
|||||||
@ -12,19 +12,6 @@ use tracing::{error, info, warn, debug};
|
|||||||
|
|
||||||
use crate::output::{display, layout};
|
use crate::output::{display, layout};
|
||||||
|
|
||||||
/* ---------- pipeline ----------------------------------------------------
|
|
||||||
* ┌────────────┐ H.264/AU ┌─────────┐ Decoded ┌─────────────┐
|
|
||||||
* │ AppSrc │────────────► decodebin ├──────────► glimagesink │
|
|
||||||
* └────────────┘ (autoplug) (overlay) |
|
|
||||||
* ----------------------------------------------------------------------*/
|
|
||||||
const PIPELINE_DESC: &str = concat!(
|
|
||||||
"appsrc name=src is-live=true format=time do-timestamp=true block=false ! ",
|
|
||||||
"queue leaky=downstream ! ",
|
|
||||||
"capsfilter caps=video/x-h264,stream-format=byte-stream,alignment=au ! ",
|
|
||||||
"h264parse disable-passthrough=true ! decodebin ! videoconvert ! ",
|
|
||||||
"glimagesink name=sink sync=false"
|
|
||||||
);
|
|
||||||
|
|
||||||
pub struct MonitorWindow {
|
pub struct MonitorWindow {
|
||||||
_pipeline: gst::Pipeline,
|
_pipeline: gst::Pipeline,
|
||||||
src: gst_app::AppSrc,
|
src: gst_app::AppSrc,
|
||||||
@ -35,7 +22,23 @@ impl MonitorWindow {
|
|||||||
gst::init().context("initialising GStreamer")?;
|
gst::init().context("initialising GStreamer")?;
|
||||||
|
|
||||||
// --- Build pipeline ---------------------------------------------------
|
// --- Build pipeline ---------------------------------------------------
|
||||||
let pipeline: gst::Pipeline = gst::parse::launch(PIPELINE_DESC)?
|
let sink = if std::env::var("GDK_BACKEND")
|
||||||
|
.map(|v| v.contains("x11"))
|
||||||
|
.unwrap_or_else(|_| std::env::var_os("DISPLAY").is_some())
|
||||||
|
{
|
||||||
|
"ximagesink name=sink sync=false"
|
||||||
|
} else {
|
||||||
|
"glimagesink name=sink sync=false"
|
||||||
|
};
|
||||||
|
|
||||||
|
let desc = format!(
|
||||||
|
"appsrc name=src is-live=true format=time do-timestamp=true block=false ! \
|
||||||
|
queue leaky=downstream ! \
|
||||||
|
capsfilter caps=video/x-h264,stream-format=byte-stream,alignment=au ! \
|
||||||
|
h264parse disable-passthrough=true ! decodebin ! videoconvert ! {sink}"
|
||||||
|
);
|
||||||
|
|
||||||
|
let pipeline: gst::Pipeline = gst::parse::launch(&desc)?
|
||||||
.downcast::<gst::Pipeline>()
|
.downcast::<gst::Pipeline>()
|
||||||
.expect("not a pipeline");
|
.expect("not a pipeline");
|
||||||
|
|
||||||
@ -59,6 +62,9 @@ impl MonitorWindow {
|
|||||||
|
|
||||||
/* -------- move/resize overlay ---------------------------------- */
|
/* -------- move/resize overlay ---------------------------------- */
|
||||||
if let Some(sink_elem) = pipeline.by_name("sink") {
|
if let Some(sink_elem) = pipeline.by_name("sink") {
|
||||||
|
if sink_elem.find_property("window-title").is_some() {
|
||||||
|
let _ = sink_elem.set_property("window-title", &format!("Lesavka-eye-{id}"));
|
||||||
|
}
|
||||||
if let Ok(overlay) = sink_elem.dynamic_cast::<VideoOverlay>() {
|
if let Ok(overlay) = sink_elem.dynamic_cast::<VideoOverlay>() {
|
||||||
if let Some(r) = rects.get(id as usize) {
|
if let Some(r) = rects.get(id as usize) {
|
||||||
// 1. Tell glimagesink how to crop the texture in its own window
|
// 1. Tell glimagesink how to crop the texture in its own window
|
||||||
@ -81,11 +87,6 @@ impl MonitorWindow {
|
|||||||
run: Arc<dyn Fn(&str) -> std::io::Result<ExitStatus> + Send + Sync>,
|
run: Arc<dyn Fn(&str) -> std::io::Result<ExitStatus> + Send + Sync>,
|
||||||
}
|
}
|
||||||
|
|
||||||
let is_kde = std::env::var("XDG_CURRENT_DESKTOP")
|
|
||||||
.unwrap_or_default()
|
|
||||||
.to_ascii_lowercase()
|
|
||||||
.contains("kde");
|
|
||||||
|
|
||||||
let placer = if Command::new("swaymsg").arg("-t").arg("get_tree")
|
let placer = if Command::new("swaymsg").arg("-t").arg("get_tree")
|
||||||
.output().is_ok()
|
.output().is_ok()
|
||||||
{
|
{
|
||||||
@ -102,30 +103,6 @@ impl MonitorWindow {
|
|||||||
.status()
|
.status()
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
} else if is_kde {
|
|
||||||
// KWin DBus script: move/resize by title
|
|
||||||
Placer {
|
|
||||||
name: "kwin",
|
|
||||||
run: Arc::new(|script| {
|
|
||||||
let dbus = if Command::new("qdbus6")
|
|
||||||
.arg("--version")
|
|
||||||
.status()
|
|
||||||
.is_ok()
|
|
||||||
{
|
|
||||||
"qdbus6"
|
|
||||||
} else {
|
|
||||||
"qdbus"
|
|
||||||
};
|
|
||||||
Command::new(dbus)
|
|
||||||
.args([
|
|
||||||
"org.kde.KWin",
|
|
||||||
"/KWin",
|
|
||||||
"org.kde.KWin.evaluateScript",
|
|
||||||
script,
|
|
||||||
])
|
|
||||||
.status()
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
Placer {
|
Placer {
|
||||||
name: "noop",
|
name: "noop",
|
||||||
@ -150,19 +127,6 @@ impl MonitorWindow {
|
|||||||
x = r.x,
|
x = r.x,
|
||||||
y = r.y,
|
y = r.y,
|
||||||
),
|
),
|
||||||
// KWin JS via DBus
|
|
||||||
"kwin" => format!(
|
|
||||||
"var clients = workspace.clientList(); \
|
|
||||||
clients.forEach(function(c) {{ \
|
|
||||||
if (c.caption === \"Lesavka-eye-{id}\") {{ \
|
|
||||||
c.geometry = {{x:{x}, y:{y}, width:{w}, height:{h}}}; \
|
|
||||||
}} \
|
|
||||||
}});",
|
|
||||||
x = r.x,
|
|
||||||
y = r.y,
|
|
||||||
w = r.w,
|
|
||||||
h = r.h,
|
|
||||||
),
|
|
||||||
_ => String::new(),
|
_ => String::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -187,7 +151,7 @@ impl MonitorWindow {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 3. X11 placement (kwin/i3/etc.) via wmctrl
|
// 3. X11 / Xwayland placement via wmctrl
|
||||||
else if std::env::var_os("DISPLAY").is_some() {
|
else if std::env::var_os("DISPLAY").is_some() {
|
||||||
let title = format!("Lesavka-eye-{id}");
|
let title = format!("Lesavka-eye-{id}");
|
||||||
let w = r.w;
|
let w = r.w;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user