Compare commits
2 commits
1be08b1b63
...
da436d5814
Author | SHA1 | Date | |
---|---|---|---|
da436d5814 | |||
3df7a93022 |
10 changed files with 388 additions and 174 deletions
|
@ -2,7 +2,7 @@
|
|||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://cnyljy7e3rf70"
|
||||
uid="uid://b2u3ggnem2sce"
|
||||
path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
|
|
|
@ -3,8 +3,14 @@ extends Node2D
|
|||
|
||||
func _on_button_pressed() -> void:
|
||||
print("Starting request in godot")
|
||||
$XdgPortals.request_screencast()
|
||||
await $ScreencastRunner.request_capture()
|
||||
print("awaiting result")
|
||||
await $ScreencastRunner.screencast_result
|
||||
|
||||
|
||||
func _on_xdg_portals_screencast_sucess(pipewire_node_id: int) -> void:
|
||||
print("Stream id in godot: ", pipewire_node_id)
|
||||
func _on_screencast_runner_screencast_failure(reason: String) -> void:
|
||||
push_warning("Screencast failed, ", reason)
|
||||
|
||||
|
||||
func _on_screencast_runner_screencast_sucess(pipewire_node_id: int) -> void:
|
||||
print("Screencast success: ", pipewire_node_id)
|
||||
|
|
|
@ -10,7 +10,8 @@ offset_right = 8.0
|
|||
offset_bottom = 8.0
|
||||
text = "Request"
|
||||
|
||||
[node name="XdgPortals" type="XdgPortals" parent="."]
|
||||
[node name="ScreencastRunner" type="ScreencastRunner" parent="."]
|
||||
|
||||
[connection signal="pressed" from="Button" to="." method="_on_button_pressed"]
|
||||
[connection signal="screencast_sucess" from="XdgPortals" to="." method="_on_xdg_portals_screencast_sucess"]
|
||||
[connection signal="screencast_failure" from="ScreencastRunner" to="." method="_on_screencast_runner_screencast_failure"]
|
||||
[connection signal="screencast_sucess" from="ScreencastRunner" to="." method="_on_screencast_runner_screencast_sucess"]
|
||||
|
|
213
rust/Cargo.lock
generated
213
rust/Cargo.lock
generated
|
@ -71,6 +71,102 @@ dependencies = [
|
|||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-channel"
|
||||
version = "2.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a"
|
||||
dependencies = [
|
||||
"concurrent-queue",
|
||||
"event-listener-strategy",
|
||||
"futures-core",
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-executor"
|
||||
version = "1.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "30ca9a001c1e8ba5149f91a74362376cc6bc5b919d92d988668657bd570bdcec"
|
||||
dependencies = [
|
||||
"async-task",
|
||||
"concurrent-queue",
|
||||
"fastrand",
|
||||
"futures-lite",
|
||||
"slab",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-fs"
|
||||
version = "2.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ebcd09b382f40fcd159c2d695175b2ae620ffa5f3bd6f664131efff4e8b9e04a"
|
||||
dependencies = [
|
||||
"async-lock",
|
||||
"blocking",
|
||||
"futures-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-io"
|
||||
version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43a2b323ccce0a1d90b449fd71f2a06ca7faa7c54c2751f06c9bd851fc061059"
|
||||
dependencies = [
|
||||
"async-lock",
|
||||
"cfg-if",
|
||||
"concurrent-queue",
|
||||
"futures-io",
|
||||
"futures-lite",
|
||||
"parking",
|
||||
"polling",
|
||||
"rustix 0.38.44",
|
||||
"slab",
|
||||
"tracing",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-lock"
|
||||
version = "3.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18"
|
||||
dependencies = [
|
||||
"event-listener",
|
||||
"event-listener-strategy",
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-net"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b948000fad4873c1c9339d60f2623323a0cfd3816e5181033c6a5cb68b2accf7"
|
||||
dependencies = [
|
||||
"async-io",
|
||||
"blocking",
|
||||
"futures-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-process"
|
||||
version = "2.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "63255f1dc2381611000436537bbedfe83183faa303a5a0edaf191edef06526bb"
|
||||
dependencies = [
|
||||
"async-channel",
|
||||
"async-io",
|
||||
"async-lock",
|
||||
"async-signal",
|
||||
"async-task",
|
||||
"blocking",
|
||||
"cfg-if",
|
||||
"event-listener",
|
||||
"futures-lite",
|
||||
"rustix 0.38.44",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-recursion"
|
||||
version = "1.1.1"
|
||||
|
@ -82,6 +178,30 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-signal"
|
||||
version = "0.2.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "637e00349800c0bdf8bfc21ebbc0b6524abea702b0da4168ac00d070d0c0b9f3"
|
||||
dependencies = [
|
||||
"async-io",
|
||||
"async-lock",
|
||||
"atomic-waker",
|
||||
"cfg-if",
|
||||
"futures-core",
|
||||
"futures-io",
|
||||
"rustix 0.38.44",
|
||||
"signal-hook-registry",
|
||||
"slab",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-task"
|
||||
version = "4.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de"
|
||||
|
||||
[[package]]
|
||||
name = "async-trait"
|
||||
version = "0.1.87"
|
||||
|
@ -93,6 +213,12 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atomic-waker"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.4.0"
|
||||
|
@ -141,6 +267,19 @@ version = "2.9.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
|
||||
|
||||
[[package]]
|
||||
name = "blocking"
|
||||
version = "1.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea"
|
||||
dependencies = [
|
||||
"async-channel",
|
||||
"async-task",
|
||||
"futures-io",
|
||||
"futures-lite",
|
||||
"piper",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "1.10.1"
|
||||
|
@ -438,6 +577,7 @@ dependencies = [
|
|||
"godot",
|
||||
"godot_tokio",
|
||||
"pipewire",
|
||||
"smol",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -447,6 +587,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "92b254068dbdb5a5a9d702039f5b741ac9a454617c28f69c5cc6c31792c7d11d"
|
||||
dependencies = [
|
||||
"godot",
|
||||
"smol",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -596,6 +737,12 @@ version = "0.5.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc"
|
||||
|
||||
[[package]]
|
||||
name = "hex"
|
||||
version = "0.4.3"
|
||||
|
@ -816,6 +963,12 @@ dependencies = [
|
|||
"system-deps",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.4.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab"
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.9.2"
|
||||
|
@ -973,6 +1126,17 @@ version = "0.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||
|
||||
[[package]]
|
||||
name = "piper"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066"
|
||||
dependencies = [
|
||||
"atomic-waker",
|
||||
"fastrand",
|
||||
"futures-io",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pipewire"
|
||||
version = "0.8.0"
|
||||
|
@ -1007,6 +1171,21 @@ version = "0.3.32"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
|
||||
|
||||
[[package]]
|
||||
name = "polling"
|
||||
version = "3.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a604568c3202727d1507653cb121dbd627a58684eb09a820fd746bee38b4442f"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"concurrent-queue",
|
||||
"hermit-abi",
|
||||
"pin-project-lite",
|
||||
"rustix 0.38.44",
|
||||
"tracing",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.21"
|
||||
|
@ -1114,6 +1293,19 @@ version = "1.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.38.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys 0.4.15",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "1.0.2"
|
||||
|
@ -1123,7 +1315,7 @@ dependencies = [
|
|||
"bitflags",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"linux-raw-sys 0.9.2",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
|
@ -1197,6 +1389,23 @@ version = "1.14.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd"
|
||||
|
||||
[[package]]
|
||||
name = "smol"
|
||||
version = "2.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a33bd3e260892199c3ccfc487c88b2da2265080acb316cd920da72fdfd7c599f"
|
||||
dependencies = [
|
||||
"async-channel",
|
||||
"async-executor",
|
||||
"async-fs",
|
||||
"async-io",
|
||||
"async-lock",
|
||||
"async-net",
|
||||
"async-process",
|
||||
"blocking",
|
||||
"futures-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
version = "0.5.8"
|
||||
|
@ -1270,7 +1479,7 @@ dependencies = [
|
|||
"fastrand",
|
||||
"getrandom",
|
||||
"once_cell",
|
||||
"rustix",
|
||||
"rustix 1.0.2",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
|
|
|
@ -5,10 +5,12 @@ edition = "2021"
|
|||
|
||||
[dependencies]
|
||||
ashpd = "0.11.0"
|
||||
gdext_coroutines = "0.7.1"
|
||||
gdext_coroutines = {version="0.7.1", features=["async"]}
|
||||
# godot = {version="0.2.4", features=["api-4-2", "experimental-godot-api", "experimental-threads"]}
|
||||
godot = "0.2.4"
|
||||
godot_tokio = "0.3.0"
|
||||
pipewire = "0.8.0"
|
||||
smol = "2.0.2"
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
|
|
@ -2,14 +2,14 @@
|
|||
#![feature(coroutine_trait)]
|
||||
#![feature(stmt_expr_attributes)]
|
||||
#![feature(unboxed_closures)]
|
||||
#![cfg_attr(feature = "async", feature(async_fn_traits))]
|
||||
//#![cfg_attr(feature = "async", feature(async_fn_traits))]
|
||||
|
||||
use godot::{classes::Engine, prelude::*};
|
||||
use godot_tokio::AsyncRuntime;
|
||||
|
||||
mod pipewire;
|
||||
mod player;
|
||||
mod portals;
|
||||
//mod screencapture;
|
||||
|
||||
struct Extension;
|
||||
|
||||
|
|
28
rust/src/pipewire/mod.rs
Normal file
28
rust/src/pipewire/mod.rs
Normal file
|
@ -0,0 +1,28 @@
|
|||
use std::thread;
|
||||
|
||||
use godot::prelude::*;
|
||||
|
||||
#[derive(GodotClass)]
|
||||
#[class(base=Node)]
|
||||
/// Node for interacting with Pipewire
|
||||
/// Intended to not be spawned manually, as the plugin will create a
|
||||
struct Pipewire {
|
||||
base: Base<Node>,
|
||||
/// Handle for the thread running the pipewire main loop
|
||||
thread_handle: Option<thread::Thread>,
|
||||
}
|
||||
|
||||
#[godot_api]
|
||||
impl INode for Pipewire {
|
||||
fn init(base: Base<Node>) -> Self {
|
||||
Self {
|
||||
base,
|
||||
thread_handle: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[godot_api]
|
||||
impl Pipewire {
|
||||
pub const SINGLETON: &'static str = "Pipewire";
|
||||
}
|
|
@ -3,14 +3,14 @@ use godot::prelude::*;
|
|||
mod screencast;
|
||||
|
||||
#[derive(GodotClass)]
|
||||
#[class(base=Object)]
|
||||
#[class(base=Node)]
|
||||
struct XdgPortals {
|
||||
base: Base<Object>,
|
||||
base: Base<Node>,
|
||||
}
|
||||
|
||||
#[godot_api]
|
||||
impl IObject for XdgPortals {
|
||||
fn init(base: Base<Object>) -> Self {
|
||||
impl INode for XdgPortals {
|
||||
fn init(base: Base<Node>) -> Self {
|
||||
Self { base }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,30 +2,93 @@ use ashpd::desktop::{
|
|||
screencast::{CursorMode, Screencast, SourceType},
|
||||
PersistMode,
|
||||
};
|
||||
use gdext_coroutines::prelude::*;
|
||||
use godot::prelude::*;
|
||||
use godot_tokio::AsyncRuntime;
|
||||
//use std::thread;
|
||||
use smol::{channel, lock::Mutex};
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(GodotClass)]
|
||||
#[class(base=RefCounted)]
|
||||
struct ScreencastResult {
|
||||
base: Base<RefCounted>,
|
||||
#[class(base = Node)]
|
||||
/// Runner node for requesting a pipewire screencast
|
||||
struct ScreencastRunner {
|
||||
base: Base<Node>,
|
||||
runner: Arc<Mutex<Runner>>,
|
||||
receiver: channel::Receiver<Result<u32, String>>,
|
||||
sender: channel::Sender<Result<u32, String>>,
|
||||
last_result: Option<Result<u32, String>>,
|
||||
}
|
||||
|
||||
#[godot_api]
|
||||
impl IRefCounted for ScreencastResult {
|
||||
fn init(base: Base<RefCounted>) -> Self {
|
||||
let mut result = Self { base };
|
||||
//thread::spawn(|| result.capture_runner());
|
||||
struct Runner;
|
||||
|
||||
result
|
||||
#[godot_api]
|
||||
impl INode for ScreencastRunner {
|
||||
fn init(base: Base<Node>) -> Self {
|
||||
let (sender, receiver) = channel::unbounded();
|
||||
Self {
|
||||
base,
|
||||
receiver,
|
||||
sender,
|
||||
runner: Arc::new(Mutex::new(Runner {})),
|
||||
last_result: None,
|
||||
}
|
||||
}
|
||||
|
||||
fn process(&mut self, _delta: f64) {
|
||||
let channel_elements = self.receiver.len();
|
||||
for _ in 0..channel_elements {
|
||||
let result = self.receiver.recv();
|
||||
let result = AsyncRuntime::block_on(result)
|
||||
.expect("Failed to receive screencast request result");
|
||||
self.last_result = Some(result.clone());
|
||||
match result {
|
||||
Ok(pipewire_node_id) => self
|
||||
.base_mut()
|
||||
.emit_signal("screencast_sucess", &[pipewire_node_id.to_variant()]),
|
||||
Err(reason) => self
|
||||
.base_mut()
|
||||
.emit_signal("screencast_failure", &[reason.to_variant()]),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[godot_api]
|
||||
impl ScreencastResult {
|
||||
fn capture_runner(&mut self) {
|
||||
AsyncRuntime::block_on(async {
|
||||
impl ScreencastRunner {
|
||||
/// Emited after a request to capture a window, if that request is successful.
|
||||
/// Contains the id of the pipewire node with the stream
|
||||
#[signal]
|
||||
fn screencast_sucess(pipewire_node_id: u32);
|
||||
/// Emited after a request to capture a window, if that request has failed.
|
||||
/// Contains the reason (as string) for why the request failed
|
||||
#[signal]
|
||||
fn screencast_failure(reason: String);
|
||||
/// Emited after a request to capture a window completes
|
||||
/// pipe_wire_node_id will contain the id of the pipewire node with the stream if ok is true
|
||||
/// reason will contain the reason (as String) why the request failed if ok is false
|
||||
/// ok indicates whether the request was successful or not
|
||||
#[signal]
|
||||
fn screencast_result(pipewire_node_id: u32, reason: String, ok: bool);
|
||||
/// Request a new window/screen capture from the user.
|
||||
/// Returns the async runner node.
|
||||
/// You can either await the `completed` result on that node
|
||||
#[func]
|
||||
fn request_capture(&mut self) -> Gd<SpireCoroutine> {
|
||||
let sender = self.sender.clone();
|
||||
let binding = self.runner.clone();
|
||||
// This is cursed. First having to spawn the task on the background runtime
|
||||
let x = AsyncRuntime::spawn(async move {
|
||||
let runner = binding.lock().await;
|
||||
runner.run_capture(sender).await;
|
||||
});
|
||||
// And then using the engine's runtime to await the completion in the background
|
||||
self.start_async_task(async move {
|
||||
let _ = x.await;
|
||||
})
|
||||
}
|
||||
}
|
||||
impl Runner {
|
||||
async fn run_capture(&self, result_chan: smol::channel::Sender<Result<u32, String>>) {
|
||||
let proxy = Screencast::new().await.expect("Screencast proxy failed");
|
||||
let session = match proxy.create_session().await {
|
||||
Ok(x) => x,
|
||||
|
@ -67,18 +130,20 @@ impl ScreencastResult {
|
|||
}
|
||||
};
|
||||
godot_print!("Got response");
|
||||
result.streams().iter().for_each(|stream| {
|
||||
// This is ugly. But I can't await inside for_each
|
||||
// so instead just collect all futures and await them in a manual loop
|
||||
let things: Vec<_> = result
|
||||
.streams()
|
||||
.iter()
|
||||
.map(|stream| {
|
||||
godot_print!("node id: {}", stream.pipe_wire_node_id());
|
||||
godot_print!("size: {:?}", stream.size());
|
||||
godot_print!("position: {:?}", stream.position());
|
||||
self.base_mut().emit_signal(
|
||||
"screencast_sucess",
|
||||
&[stream.pipe_wire_node_id().to_variant()],
|
||||
);
|
||||
});
|
||||
});
|
||||
result_chan.send(Ok(stream.pipe_wire_node_id()))
|
||||
})
|
||||
.collect();
|
||||
for future in things {
|
||||
let _ = future.await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Send for ScreencastResult {}
|
||||
unsafe impl Sync for ScreencastResult {}
|
||||
|
|
|
@ -1,97 +0,0 @@
|
|||
use ashpd::desktop::{
|
||||
screencast::{CursorMode, Screencast, SourceType},
|
||||
PersistMode,
|
||||
};
|
||||
use godot::classes::{INode, Node};
|
||||
use godot::prelude::*;
|
||||
use godot_tokio::AsyncRuntime;
|
||||
|
||||
#[derive(GodotClass)]
|
||||
#[class(base=Node)]
|
||||
struct XdgPortals {
|
||||
base: Base<Node>,
|
||||
last_request_completed: bool,
|
||||
}
|
||||
|
||||
#[godot_api]
|
||||
impl INode for XdgPortals {
|
||||
fn init(base: Base<Node>) -> Self {
|
||||
Self {
|
||||
base,
|
||||
last_request_completed: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[godot_api]
|
||||
impl XdgPortals {
|
||||
#[signal]
|
||||
fn screencast_sucess(pipewire_node_id: u32);
|
||||
|
||||
#[func]
|
||||
fn was_last_request_completed(&self) -> bool {
|
||||
self.last_request_completed
|
||||
}
|
||||
|
||||
#[func]
|
||||
fn request_screencast(&mut self) {
|
||||
godot_print!("Starting request");
|
||||
self.last_request_completed = false;
|
||||
AsyncRuntime::block_on(async {
|
||||
godot_print!("Starting request async");
|
||||
let proxy = Screencast::new().await.expect("Screencast proxy failed");
|
||||
let session = match proxy.create_session().await {
|
||||
Ok(x) => x,
|
||||
Err(err) => {
|
||||
godot_warn!("Failed to create session: {}", err);
|
||||
return;
|
||||
}
|
||||
};
|
||||
godot_print!("Got proxy");
|
||||
match proxy
|
||||
.select_sources(
|
||||
&session,
|
||||
CursorMode::Metadata,
|
||||
SourceType::Monitor | SourceType::Window,
|
||||
true,
|
||||
None,
|
||||
PersistMode::DoNot,
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(_) => {}
|
||||
Err(err) => {
|
||||
godot_warn!("Err while selecting source: {}", err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
godot_print!("Selected source");
|
||||
|
||||
let starter = match proxy.start(&session, None).await {
|
||||
Ok(x) => x,
|
||||
Err(err) => {
|
||||
godot_warn!("Error while starting: {}", err);
|
||||
return;
|
||||
}
|
||||
};
|
||||
let result = match starter.response() {
|
||||
Ok(x) => x,
|
||||
Err(err) => {
|
||||
godot_warn!("Err for response: {}", err);
|
||||
return;
|
||||
}
|
||||
};
|
||||
godot_print!("Got response");
|
||||
result.streams().iter().for_each(|stream| {
|
||||
godot_print!("node id: {}", stream.pipe_wire_node_id());
|
||||
godot_print!("size: {:?}", stream.size());
|
||||
godot_print!("position: {:?}", stream.position());
|
||||
self.base_mut().emit_signal(
|
||||
"screencast_sucess",
|
||||
&[stream.pipe_wire_node_id().to_variant()],
|
||||
);
|
||||
self.last_request_completed = true;
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue