use thiserror::Error;
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum CaptureError {
#[error("the user cancelled the capture request")]
Cancelled,
#[error("screen capture permission was denied")]
PermissionDenied,
#[error("no capture target matched")]
TargetNotFound,
#[cfg(any(target_os = "windows", target_os = "macos"))]
#[error("the window name pattern is not a valid regex: {0}")]
BadWindowRegex(#[from] regex::Error),
#[error("channel_capacity must be at least 1")]
ZeroChannelCapacity,
#[error("unsupported on this system: {0}")]
Unsupported(#[from] Unsupported),
#[error("the capture thread terminated unexpectedly")]
WorkerGone,
#[allow(missing_docs)]
#[error("IO error: {0}")]
IO(#[from] std::io::Error),
#[cfg(target_os = "windows")]
#[allow(missing_docs)]
#[error("Failed to call Windows Api: {0}")]
Win(#[from] windows::core::Error),
#[cfg(target_os = "linux")]
#[allow(missing_docs)]
#[error("Failed to call D-Bus Api: {0}")]
Dbus(#[from] dbus::Error),
#[cfg(target_os = "linux")]
#[allow(missing_docs)]
#[error("Failed to call PipeWire Api: {0}")]
Pipewire(#[from] pipewire::Error),
#[cfg(target_os = "linux")]
#[error("the ScreenCast portal: {0}")]
Portal(#[from] PortalError),
#[cfg(target_os = "linux")]
#[error("the PipeWire stream failed before agreeing on a format")]
StreamFailed,
#[cfg(target_os = "linux")]
#[error("could not build the PipeWire stream parameters")]
SpaParams,
#[cfg(target_os = "macos")]
#[error("ScreenCaptureKit: {0}")]
ScreenCaptureKit(#[from] ScreenCaptureKitError),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Error)]
#[non_exhaustive]
pub enum Unsupported {
#[error("screen capture")]
ScreenCapture,
#[error("Direct3D 11")]
Direct3D,
#[error("hiding windows from the capture")]
HideWindows,
#[error("capturing a single window")]
WindowTarget,
#[error("the system picker")]
Picker,
#[error("capturing audio")]
Audio,
#[error("the negotiated audio sample format")]
SampleFormat,
}
#[cfg(target_os = "linux")]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum PortalCall {
CreateSession,
SelectSources,
Start,
}
#[cfg(target_os = "linux")]
impl core::fmt::Display for PortalCall {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_str(match self {
Self::CreateSession => "CreateSession",
Self::SelectSources => "SelectSources",
Self::Start => "Start",
})
}
}
#[cfg(target_os = "linux")]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Error)]
#[non_exhaustive]
pub enum PortalError {
#[error("no source of the requested kind (wanted {wanted:#x}, available {available:#x})")]
NoMatchingSource {
wanted: u32,
available: u32,
},
#[error("{call} failed with response {response}")]
Refused {
call: PortalCall,
response: u32,
},
#[error("{call} returned a malformed reply")]
MalformedReply {
call: PortalCall,
},
#[error("the portal left the bus before answering {call}")]
Vanished {
call: PortalCall,
},
}
#[cfg(target_os = "macos")]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Error)]
#[non_exhaustive]
pub enum ScreenCaptureKitError {
#[error("no shareable content")]
NoShareableContent,
#[error("the stream failed to start")]
FailedToStart,
#[error("the system stopped the stream")]
Stopped,
#[error("the stream output could not be attached")]
OutputAttach,
#[error("SCStream error {0}")]
Stream(isize),
#[error("error {0} from another error domain")]
Other(isize),
}
pub type Result<T> = core::result::Result<T, CaptureError>;