mirror of
https://gitlab.freedesktop.org/pipewire/helvum
synced 2026-03-15 11:36:11 +08:00
Modify architecture to run pipewire loop in second thread.
The pipewire loop now runs without interruption in a second thread and communicates with the GTK thread via a channel in each direction, instead of checking for events once a second and using callbacks. This allows changes to appear instantly in the view, instead of having to wait.
This commit is contained in:
57
src/main.rs
57
src/main.rs
@@ -4,7 +4,38 @@ mod view;
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
use gtk::{glib, prelude::*};
|
||||
use controller::MediaType;
|
||||
use gtk::glib::{self, PRIORITY_DEFAULT};
|
||||
use pipewire::spa::Direction;
|
||||
|
||||
/// Messages used GTK thread to command the pipewire thread.
|
||||
#[derive(Debug)]
|
||||
enum GtkMessage {
|
||||
/// Quit the event loop and let the thread finish.
|
||||
Terminate,
|
||||
}
|
||||
|
||||
/// Messages used pipewire thread to notify the GTK thread.
|
||||
#[derive(Debug)]
|
||||
enum PipewireMessage {
|
||||
/// A new node has appeared.
|
||||
NodeAdded {
|
||||
id: u32,
|
||||
name: String,
|
||||
media_type: Option<MediaType>,
|
||||
},
|
||||
/// A new port has appeared.
|
||||
PortAdded {
|
||||
id: u32,
|
||||
node_id: u32,
|
||||
name: String,
|
||||
direction: Direction,
|
||||
},
|
||||
/// A new link has appeared.
|
||||
LinkAdded { id: u32, link: PipewireLink },
|
||||
/// An object was removed
|
||||
ObjectRemoved { id: u32 },
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PipewireLink {
|
||||
@@ -18,20 +49,22 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
env_logger::init();
|
||||
gtk::init()?;
|
||||
|
||||
let view = Rc::new(view::View::new());
|
||||
let pw_con = pipewire_connection::PipewireConnection::new()?;
|
||||
let _controller = controller::Controller::new(view.clone(), pw_con.clone());
|
||||
// Start the pipewire thread with channels in both directions.
|
||||
let (gtk_sender, gtk_receiver) = glib::MainContext::channel(PRIORITY_DEFAULT);
|
||||
let (pw_sender, pw_receiver) = pipewire::channel::channel();
|
||||
let pw_thread =
|
||||
std::thread::spawn(move || pipewire_connection::thread_main(gtk_sender, pw_receiver));
|
||||
|
||||
// Do an initial roundtrip before showing the view,
|
||||
// so that the graph is already populated when the window opens.
|
||||
pw_con.borrow().roundtrip();
|
||||
// From now on, call roundtrip() every second.
|
||||
glib::timeout_add_seconds_local(1, move || {
|
||||
pw_con.borrow().roundtrip();
|
||||
Continue(true)
|
||||
});
|
||||
let view = Rc::new(view::View::new());
|
||||
let _controller = controller::Controller::new(view.clone(), gtk_receiver);
|
||||
|
||||
view.run();
|
||||
|
||||
pw_sender
|
||||
.send(GtkMessage::Terminate)
|
||||
.expect("Failed to send message");
|
||||
|
||||
pw_thread.join().expect("Pipewire thread panicked");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user