Fix compositor output routing and pointer hints; format imports

This commit is contained in:
Samuel Onoja committed 2026-09-30 06:39:58 +01:00
1 parent 88e4f3c135
commit 46509f880a
108 files changed
+3682 -8371

No files matched your search

+24 -49
View File
@@ -1,17 +1,17 @@
//! PipeWire runs outside the compositor. Keep one frame, drop old frames under
//! backpressure, and destroy the node when the portal's control pipe closes.
use crate::capture::{Capture, Frame};
use pipewire::{self as pw, properties::properties, spa};
use std::io::{Read, Write};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Mutex};
use std::time::{Duration, Instant};
use pipewire as pw;
use pipewire::properties::properties;
use pipewire::spa;
use serde::{Deserialize, Serialize};
use spa::pod::Pod;
use std::{
io::{Read, Write},
sync::{
Arc, Mutex,
atomic::{AtomicBool, Ordering},
},
time::{Duration, Instant},
};
use crate::capture::{Capture, Frame};
#[derive(Debug, Serialize, Deserialize)]
pub struct Ready {
@@ -70,10 +70,7 @@ impl<'a> OutputBuffer<'a> {
)
.cast::<spa::sys::spa_meta_header>();
if let Some(header) = header.as_mut() {
let mut now = libc::timespec {
tv_sec: 0,
tv_nsec: 0,
};
let mut now = libc::timespec { tv_sec: 0, tv_nsec: 0 };
header.pts = if libc::clock_gettime(libc::CLOCK_MONOTONIC, &mut now) == 0 {
now.tv_sec * 1_000_000_000 + now.tv_nsec
} else {
@@ -104,13 +101,10 @@ fn int_property(key: u32, value: i32) -> spa::pod::Property {
}
}
fn pod(object: spa::pod::Object) -> Vec<u8> {
spa::pod::serialize::PodSerializer::serialize(
std::io::Cursor::new(Vec::new()),
&spa::pod::Value::Object(object),
)
.unwrap()
.0
.into_inner()
spa::pod::serialize::PodSerializer::serialize(std::io::Cursor::new(Vec::new()), &spa::pod::Value::Object(object))
.unwrap()
.0
.into_inner()
}
fn video_format(width: u32, height: u32) -> Vec<u8> {
@@ -145,11 +139,7 @@ fn video_format(width: u32, height: u32) -> Vec<u8> {
))
}
pub fn run(
name: String,
cursor: bool,
generation: Option<u32>,
) -> Result<(), Box<dyn std::error::Error>> {
pub fn run(name: String, cursor: bool, generation: Option<u32>) -> Result<(), Box<dyn std::error::Error>> {
let stop = Arc::new(AtomicBool::new(false));
let pipe_stop = stop.clone();
std::thread::spawn(move || {
@@ -213,14 +203,10 @@ pub fn run(
.add_local_listener_with_user_data(data)
.state_changed(move |stream, data, _, state| {
data.fresh.store(false, Ordering::SeqCst);
data.streaming.store(
matches!(state, pw::stream::StreamState::Streaming),
Ordering::Relaxed,
);
data.streaming
.store(matches!(state, pw::stream::StreamState::Streaming), Ordering::Relaxed);
match state {
pw::stream::StreamState::Paused | pw::stream::StreamState::Streaming
if !data.announced =>
{
pw::stream::StreamState::Paused | pw::stream::StreamState::Streaming if !data.announced => {
let node = stream.node_id();
if node != u32::MAX {
data.announced = true;
@@ -257,8 +243,7 @@ pub fn run(
|| format.size().width == 0
|| format.size().height == 0
|| (!resizable && (format.size().width, format.size().height) != (width, height))
|| u64::from(format.size().width) * u64::from(format.size().height) * 4
> 128 * 1024 * 1024
|| u64::from(format.size().width) * u64::from(format.size().height) * 4 > 128 * 1024 * 1024
|| format.format() != spa::param::video::VideoFormat::BGRx
{
data.stop.store(true, Ordering::Relaxed);
@@ -271,10 +256,7 @@ pub fn run(
spa::param::ParamType::Buffers,
int_property(spa::sys::SPA_PARAM_BUFFERS_buffers, 4),
int_property(spa::sys::SPA_PARAM_BUFFERS_blocks, 1),
int_property(
spa::sys::SPA_PARAM_BUFFERS_size,
(width * height * 4) as i32
),
int_property(spa::sys::SPA_PARAM_BUFFERS_size, (width * height * 4) as i32),
int_property(spa::sys::SPA_PARAM_BUFFERS_stride, (width * 4) as i32),
int_property(spa::sys::SPA_PARAM_BUFFERS_align, 16)
));
@@ -292,10 +274,7 @@ pub fn run(
)
));
if stream
.update_params(&mut [
Pod::from_bytes(&buffers).unwrap(),
Pod::from_bytes(&header).unwrap(),
])
.update_params(&mut [Pod::from_bytes(&buffers).unwrap(), Pod::from_bytes(&header).unwrap()])
.is_err()
{
data.stop.store(true, Ordering::Relaxed);
@@ -358,9 +337,7 @@ pub fn run(
while !capture_stop.load(Ordering::Relaxed) {
let start = Instant::now();
if capture_streaming.load(Ordering::Relaxed)
|| checked.elapsed() >= Duration::from_secs(1)
{
if capture_streaming.load(Ordering::Relaxed) || checked.elapsed() >= Duration::from_secs(1) {
checked = Instant::now();
match capture.frame(&name, cursor, &capture_stop, std::mem::take(&mut spare)) {
Ok(frame) if resizable || (frame.width == width && frame.height == height) => {
@@ -407,9 +384,7 @@ pub fn run(
} else {
Duration::from_millis(10)
};
mainloop
.loop_()
.iterate(pw::loop_::Timeout::Finite(timeout));
mainloop.loop_().iterate(pw::loop_::Timeout::Finite(timeout));
if streaming.load(Ordering::Relaxed) && Instant::now() >= next_frame {
let _ = stream.trigger_process();
next_frame = Instant::now() + interval;