Introduce IPC socket
This commit is contained in:
parent
8959cce9f9
commit
a31baa3670
@ -21,6 +21,7 @@ toml = "0.9.8"
|
|||||||
popcorn-conf = { path = "../popcorn-conf" }
|
popcorn-conf = { path = "../popcorn-conf" }
|
||||||
serde = { version = "1.0.228", features = ["derive"] }
|
serde = { version = "1.0.228", features = ["derive"] }
|
||||||
popcorn-proto = { path = "../popcorn-proto" }
|
popcorn-proto = { path = "../popcorn-proto" }
|
||||||
|
bincode = "1.3.3"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
slint-build = "1.14.1"
|
slint-build = "1.14.1"
|
||||||
|
|||||||
56
crates/popcorn-d/src/ipc.rs
Normal file
56
crates/popcorn-d/src/ipc.rs
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
use std::fs;
|
||||||
|
use std::io::Read;
|
||||||
|
use std::os::unix::net::{UnixListener, UnixStream};
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::sync::mpsc::Sender;
|
||||||
|
|
||||||
|
use dirs::runtime_dir;
|
||||||
|
use popcorn_proto::OsdArgs;
|
||||||
|
|
||||||
|
/// Start a Unix socket server and forward received messages to the UI thread.
|
||||||
|
pub fn start_ipc(tx: Sender<OsdArgs>) -> std::io::Result<()> {
|
||||||
|
let sock_path = socket_path();
|
||||||
|
|
||||||
|
// Remove leftover socket from a previous run.
|
||||||
|
let _ = fs::remove_file(&sock_path);
|
||||||
|
|
||||||
|
// Create parent directory if missing.
|
||||||
|
if let Some(parent) = sock_path.parent() {
|
||||||
|
fs::create_dir_all(parent)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bind the Unix domain socket.
|
||||||
|
let listener = UnixListener::bind(&sock_path)?;
|
||||||
|
|
||||||
|
// Run the IPC accept loop in a background thread.
|
||||||
|
std::thread::spawn(move || {
|
||||||
|
// Accept short-lived connections.
|
||||||
|
for stream in listener.incoming() {
|
||||||
|
if let Ok(stream) = stream {
|
||||||
|
// Read one message per connection.
|
||||||
|
if let Ok(args) = read_message(stream) {
|
||||||
|
// Forward to UI thread via channel.
|
||||||
|
let _ = tx.send(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read a single serialized OsdArgs message from a socket.
|
||||||
|
fn read_message(mut stream: UnixStream) -> bincode::Result<OsdArgs> {
|
||||||
|
let mut buf = Vec::new();
|
||||||
|
// Read until client closes the connection.
|
||||||
|
stream.read_to_end(&mut buf)?;
|
||||||
|
// Deserialize binary message.
|
||||||
|
bincode::deserialize(&buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Compute the per-user runtime socket path.
|
||||||
|
fn socket_path() -> PathBuf {
|
||||||
|
// Prefer XDG runtime dir. Fallback to /tmp.
|
||||||
|
let base = runtime_dir().unwrap_or_else(|| PathBuf::from("/tmp"));
|
||||||
|
base.join("candywidgets").join("popcorn.sock")
|
||||||
|
}
|
||||||
@ -1,18 +1,38 @@
|
|||||||
|
mod ipc;
|
||||||
mod osd;
|
mod osd;
|
||||||
|
|
||||||
use osd::OsdUi;
|
use osd::OsdUi;
|
||||||
use popcorn_conf::PopcornConfig;
|
use popcorn_conf::PopcornConfig;
|
||||||
|
use popcorn_proto::OsdArgs;
|
||||||
|
|
||||||
|
use std::sync::mpsc;
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
// Load configuration once at startup.
|
||||||
let cfg = PopcornConfig::load_or_default();
|
let cfg = PopcornConfig::load_or_default();
|
||||||
|
|
||||||
|
// Create the OSD UI on the main (UI) thread.
|
||||||
let osd = OsdUi::new(&cfg)?;
|
let osd = OsdUi::new(&cfg)?;
|
||||||
|
|
||||||
// start IPC loop here
|
// Channel used to send IPC messages to the UI thread.
|
||||||
// for each message:
|
let (tx, rx) = mpsc::channel::<OsdArgs>();
|
||||||
// osd.update(&args, &cfg)
|
|
||||||
// reset timer
|
|
||||||
|
|
||||||
let _ = slint::run_event_loop();
|
// Start IPC server in a background thread.
|
||||||
|
ipc::start_ipc(tx)?;
|
||||||
|
|
||||||
|
// Poll IPC messages on the UI thread.
|
||||||
|
slint::Timer::default().start(
|
||||||
|
slint::TimerMode::Repeated,
|
||||||
|
std::time::Duration::from_millis(16),
|
||||||
|
move || {
|
||||||
|
// Process all pending messages.
|
||||||
|
while let Ok(args) = rx.try_recv() {
|
||||||
|
let _ = osd.update(&args, &cfg);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// Run the Slint event loop.
|
||||||
|
slint::run_event_loop();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,5 +12,6 @@ keywords = ["OSD", "popup", "desktop", "cli"]
|
|||||||
license = "GPL-3+"
|
license = "GPL-3+"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
bincode = "1.3.3"
|
||||||
clap = { version = "4.5.53", features = ["derive"] }
|
clap = { version = "4.5.53", features = ["derive"] }
|
||||||
popcorn-proto = { path = "../popcorn-proto" }
|
popcorn-proto = { path = "../popcorn-proto" }
|
||||||
@ -1,8 +1,8 @@
|
|||||||
mod args;
|
mod args;
|
||||||
|
|
||||||
use args::CliArgs;
|
use args::CliArgs;
|
||||||
use popcorn_proto::OsdArgs;
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
use popcorn_proto::OsdArgs;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let cli = CliArgs::parse();
|
let cli = CliArgs::parse();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user