fix: time out a stalled portal and sample motion across segments
Hyprland's portal sometimes creates the session and never answers source selection, before any picker appears. Recording now fails if the portal has not reached its picker within 10 s; time in the picker is not limited. The motion check uses the segment with the most motion, since capture can start late.
This commit is contained in:
@@ -176,6 +176,14 @@ fn pipewire_state(message: &str) -> Option<PipeWireState> {
|
||||
PipeWireState::Stopped
|
||||
});
|
||||
}
|
||||
// Requested from the portal, then the picker is shown (or a restore
|
||||
// token is used): only the first step can stall without the user.
|
||||
if message == "PipeWire initialized" {
|
||||
return Some(PipeWireState::Requesting);
|
||||
}
|
||||
if message.starts_with("[pipewire] Asking for ") {
|
||||
return Some(PipeWireState::Selecting);
|
||||
}
|
||||
// The user denied or cancelled the portal request, or it failed.
|
||||
let refused = message.starts_with("[pipewire] Error ")
|
||||
|| (message.starts_with("[pipewire] Failed to ")
|
||||
@@ -185,6 +193,8 @@ fn pipewire_state(message: &str) -> Option<PipeWireState> {
|
||||
|
||||
fn load_pipewire_state() -> Option<PipeWireState> {
|
||||
match PIPEWIRE_STATE.load(Ordering::Relaxed) {
|
||||
state if state == PipeWireState::Requesting as u8 => Some(PipeWireState::Requesting),
|
||||
state if state == PipeWireState::Selecting as u8 => Some(PipeWireState::Selecting),
|
||||
state if state == PipeWireState::Streaming as u8 => Some(PipeWireState::Streaming),
|
||||
state if state == PipeWireState::Stopped as u8 => Some(PipeWireState::Stopped),
|
||||
state if state == PipeWireState::Refused as u8 => Some(PipeWireState::Refused),
|
||||
@@ -877,6 +887,14 @@ mod tests {
|
||||
state("[pipewire] Error selecting screencast source: Timeout"),
|
||||
Some(PipeWireState::Refused)
|
||||
);
|
||||
assert_eq!(
|
||||
state("PipeWire initialized"),
|
||||
Some(PipeWireState::Requesting)
|
||||
);
|
||||
assert_eq!(
|
||||
state("[pipewire] Asking for monitor and window"),
|
||||
Some(PipeWireState::Selecting)
|
||||
);
|
||||
assert_eq!(state("[pipewire] Screencast session created"), None);
|
||||
// OBS cancelling its own pending request at teardown is not a refusal.
|
||||
assert_eq!(state("[portals] Request cancelled"), None);
|
||||
|
||||
Reference in New Issue
Block a user