Compare commits

..

No commits in common. "64210b19831c746b39341c3115f89d56f43852b6" and "da436d5814e93eaa787e4ab56cd101ebeff5e06a" have entirely different histories.

5 changed files with 13 additions and 82 deletions

View file

@ -1,12 +0,0 @@
default:
@just --list
build-rust:
cd rust && cargo build
run-godot:
cd learning-rust4.4 && ~/Software/Godot_v4.4-stable_linux.x86_64 .
run:
@just build-rust
@just run-godot

View file

@ -6,8 +6,6 @@ edition = "2021"
[dependencies]
ashpd = "0.11.0"
gdext_coroutines = {version="0.7.1", features=["async"]}
# Use this specific commit until hot reload is fixed in main
# gdext_coroutines = { git="https://github.com/Houtamelo/gdext_coroutines", rev="afd3c7e", 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"

View file

@ -6,7 +6,6 @@
use godot::{classes::Engine, prelude::*};
use godot_tokio::AsyncRuntime;
use pipewire::Pipewire;
mod pipewire;
mod player;
@ -17,14 +16,11 @@ struct Extension;
#[gdextension]
unsafe impl ExtensionLibrary for Extension {
fn on_level_init(level: InitLevel) {
#[cfg(not(target_os = "linux"))]
panic!("Not supported on Windows");
if level == InitLevel::Scene {
let mut engine = Engine::singleton();
// This is where we register our async runtime singleton.
engine.register_singleton(AsyncRuntime::SINGLETON, &AsyncRuntime::new_alloc());
engine.register_singleton(Pipewire::SINGLETON, &Pipewire::new_alloc());
}
}
fn on_level_deinit(level: InitLevel) {
@ -32,19 +28,15 @@ unsafe impl ExtensionLibrary for Extension {
let mut engine = Engine::singleton();
// Here is where we free our async runtime singleton from memory.
Extension::free_singleton(&mut engine, AsyncRuntime::SINGLETON);
Extension::free_singleton(&mut engine, Pipewire::SINGLETON);
}
}
}
impl Extension {
fn free_singleton(engine: &mut Engine, name: &str) {
if let Some(async_singleton) = engine.get_singleton(name) {
engine.unregister_singleton(name);
if let Some(async_singleton) = engine.get_singleton(AsyncRuntime::SINGLETON) {
engine.unregister_singleton(AsyncRuntime::SINGLETON);
async_singleton.free();
} else {
godot_warn!("Failed to find & free singleton -> {}", name);
godot_warn!(
"Failed to find & free singleton -> {}",
AsyncRuntime::SINGLETON
);
}
}
}
}

View file

@ -1,46 +1,23 @@
use std::thread;
use godot::{classes::notify::NodeNotification, prelude::*};
use pipewire::{
channel::{Receiver, Sender},
main_loop::MainLoop,
};
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
pub(crate) struct Pipewire {
struct Pipewire {
base: Base<Node>,
/// Handle for the thread running the pipewire main loop
thread_handle: Option<thread::JoinHandle<()>>,
shutdown_sender: Sender<Terminate>,
thread_handle: Option<thread::Thread>,
}
struct Terminate;
#[godot_api]
impl INode for Pipewire {
fn init(base: Base<Node>) -> Self {
let (thread, shutdown_sender) = Self::start_pipewire_thread();
Self {
base,
thread_handle: Some(thread),
shutdown_sender,
}
}
fn on_notification(&mut self, what: NodeNotification) {
if what == NodeNotification::PREDELETE
|| what == NodeNotification::UNPARENTED
|| what == NodeNotification::WM_CLOSE_REQUEST
|| what == NodeNotification::EXIT_TREE
{
godot_print!("Sending shutdown signal to pipewire thread");
let _ = self.shutdown_sender.send(Terminate {});
let handle = self.thread_handle.take().unwrap();
let _join_result = handle.join();
godot_print!("Pipewire thread completed");
thread_handle: None,
}
}
}
@ -48,26 +25,4 @@ impl INode for Pipewire {
#[godot_api]
impl Pipewire {
pub const SINGLETON: &'static str = "Pipewire";
fn start_pipewire_thread() -> (thread::JoinHandle<()>, Sender<Terminate>) {
godot_print!("Starting pipewire thread");
let (shutdown_sender, shutdown_receiver) = pipewire::channel::channel::<Terminate>();
let thread_handle = thread::spawn(|| Self::pipewire_main(shutdown_receiver));
(thread_handle, shutdown_sender)
}
/// Func that actually runs the main loop in the thread
fn pipewire_main(shutdown_receiver: Receiver<Terminate>) {
let mainloop = MainLoop::new(None).expect("Failed to create pipewire main loop");
let _receiver = shutdown_receiver.attach(mainloop.loop_(), {
godot_print!("Stopping pipewire thread");
let mainloop = mainloop.clone();
move |_| mainloop.quit()
});
godot_print!("Entering pipewire main loop");
mainloop.run();
println!("Pipewire main loop exited");
}
}

View file

@ -24,8 +24,6 @@ struct Runner;
#[godot_api]
impl INode for ScreencastRunner {
fn init(base: Base<Node>) -> Self {
#[cfg(not(target_os = "linux"))]
panic!("Not supported on Windows");
let (sender, receiver) = channel::unbounded();
Self {
base,