Skip to main content

pinray_core/
config.rs

1use crate::{
2    error::{PinrayError, Result},
3    frame::{ColorSpace, PixelFormat, Rect},
4    source::SourceId,
5};
6
7/// Whether the pointer is drawn into captured frames.
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum CursorMode {
10    Embedded,
11    Hidden,
12}
13
14/// What to capture video from; ids come from source enumeration or
15/// `SourceId::new("auto")` for the primary display.
16#[derive(Debug, Clone, PartialEq, Eq)]
17pub enum VideoCaptureTarget {
18    Display(SourceId),
19    Window(SourceId),
20}
21
22/// What to capture audio from.
23#[derive(Debug, Clone, PartialEq, Eq)]
24pub enum AudioCapture {
25    /// Everything the system plays (loopback / sink monitor).
26    SystemMix,
27    /// A microphone device (not implemented by any backend yet).
28    Microphone(SourceId),
29}
30
31/// Validated session configuration; construct through the session builder.
32#[derive(Debug, Clone, PartialEq, Eq)]
33pub struct SessionConfig {
34    pub backend_preference: crate::backend::BackendPreference,
35    pub video_target: Option<VideoCaptureTarget>,
36    pub audio_capture: Option<AudioCapture>,
37    pub restore_token: Option<String>,
38    pub pixel_format: PixelFormat,
39    pub color_space: Option<ColorSpace>,
40    pub cursor_mode: CursorMode,
41    pub crop_rect: Option<Rect>,
42    pub frame_rate: Option<u32>,
43    pub queue_depth: u32,
44}
45
46impl Default for SessionConfig {
47    fn default() -> Self {
48        Self {
49            backend_preference: crate::backend::BackendPreference::Auto,
50            video_target: None,
51            audio_capture: None,
52            restore_token: None,
53            pixel_format: PixelFormat::Bgra8888,
54            color_space: Some(ColorSpace::Srgb),
55            cursor_mode: CursorMode::Embedded,
56            crop_rect: None,
57            frame_rate: Some(60),
58            queue_depth: 2,
59        }
60    }
61}
62
63impl SessionConfig {
64    pub fn validate(&self) -> Result<()> {
65        if self.video_target.is_none() && self.audio_capture.is_none() {
66            return Err(PinrayError::InvalidConfig(
67                "at least one of video_target or audio_capture must be set".into(),
68            ));
69        }
70
71        if let Some(frame_rate) = self.frame_rate
72            && frame_rate == 0
73        {
74            return Err(PinrayError::InvalidConfig(
75                "frame_rate must be greater than zero".into(),
76            ));
77        }
78
79        if self.queue_depth == 0 {
80            return Err(PinrayError::InvalidConfig(
81                "queue_depth must be greater than zero".into(),
82            ));
83        }
84
85        if let Some(rect) = self.crop_rect
86            && (rect.width == 0 || rect.height == 0)
87        {
88            return Err(PinrayError::InvalidConfig(
89                "crop_rect width and height must be greater than zero".into(),
90            ));
91        }
92
93        Ok(())
94    }
95}