Skip to main content

screencapturekit/stream/configuration/
mod.rs

1mod internal;
2
3pub mod advanced;
4pub mod audio;
5pub mod captured_elements;
6pub mod captured_frames;
7pub mod colors;
8pub mod dimensions;
9pub mod pixel_format;
10pub mod stream_properties;
11
12pub use advanced::SCPresenterOverlayAlertSetting;
13pub use audio::{AudioChannelCount, AudioSampleRate};
14pub use captured_frames::{MAX_QUEUE_DEPTH, MIN_QUEUE_DEPTH};
15pub use colors::{color_matrix, color_space, InteriorNulError};
16pub use internal::SCStreamConfiguration;
17pub use pixel_format::PixelFormat;
18pub use stream_properties::SCCaptureDynamicRange;
19
20/// Capture resolution type for stream configuration (macOS 14.0+)
21///
22/// Controls how the capture resolution is determined relative to the source content.
23#[repr(i32)]
24#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
25#[cfg(feature = "macos_14_0")]
26pub enum SCCaptureResolutionType {
27    /// Automatically determines the best resolution
28    #[default]
29    Automatic = 0,
30    /// Uses the best available resolution (highest quality)
31    Best = 1,
32    /// Uses the nominal resolution of the display
33    Nominal = 2,
34}
35
36#[cfg(feature = "macos_14_0")]
37impl SCCaptureResolutionType {
38    pub const fn from_raw(raw: i32) -> Option<Self> {
39        match raw {
40            0 => Some(Self::Automatic),
41            1 => Some(Self::Best),
42            2 => Some(Self::Nominal),
43            _ => None,
44        }
45    }
46}
47
48#[cfg(feature = "macos_14_0")]
49impl std::fmt::Display for SCCaptureResolutionType {
50    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
51        match self {
52            Self::Automatic => write!(f, "Automatic"),
53            Self::Best => write!(f, "Best"),
54            Self::Nominal => write!(f, "Nominal"),
55        }
56    }
57}
58
59impl Default for SCStreamConfiguration {
60    fn default() -> Self {
61        Self::internal_init()
62    }
63}
64
65/// Preset for creating stream configurations (macOS 15.0+)
66///
67/// Use these presets to create configurations optimized for specific use cases,
68/// particularly HDR capture scenarios.
69#[repr(i32)]
70#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
71#[cfg(feature = "macos_15_0")]
72pub enum SCStreamConfigurationPreset {
73    /// HDR stream optimized for local display
74    CaptureHDRStreamLocalDisplay = 0,
75    /// HDR stream optimized for canonical display
76    CaptureHDRStreamCanonicalDisplay = 1,
77    /// HDR screenshot optimized for local display
78    CaptureHDRScreenshotLocalDisplay = 2,
79    /// HDR screenshot optimized for canonical display
80    CaptureHDRScreenshotCanonicalDisplay = 3,
81    /// HDR recording optimized for HDR10, preserving SDR range during playback.
82    ///
83    /// This preset sets values for `captureDynamicRange`, `pixelFormat`, and `colorSpace`
84    /// intended for a stream recording in HDR10, optimized for rendering on the
85    /// canonical HDR display. It also adds HDR10 metadata to the video recording
86    /// that is designed to preserve the SDR range during video playback.
87    #[cfg(feature = "macos_26_0")]
88    CaptureHDRRecordingPreservedSDRHDR10 = 4,
89}
90
91impl SCStreamConfiguration {
92    /// Create a new stream configuration with default values
93    ///
94    /// This is equivalent to `SCStreamConfiguration::default()`.
95    ///
96    /// # Examples
97    ///
98    /// ```
99    /// use screencapturekit::prelude::*;
100    ///
101    /// let config = SCStreamConfiguration::new()
102    ///     .with_width(1920)
103    ///     .with_height(1080);
104    /// ```
105    #[must_use]
106    pub fn new() -> Self {
107        Self::default()
108    }
109
110    /// Create a configuration from a preset (macOS 15.0+)
111    ///
112    /// Presets provide optimized default values for specific use cases,
113    /// particularly for HDR capture.
114    ///
115    /// # Examples
116    ///
117    /// ```no_run
118    /// use screencapturekit::stream::configuration::{SCStreamConfiguration, SCStreamConfigurationPreset};
119    ///
120    /// let config = SCStreamConfiguration::from_preset(SCStreamConfigurationPreset::CaptureHDRStreamLocalDisplay)
121    ///     .expect("macOS 15.0 or later");
122    /// ```
123    #[cfg(feature = "macos_15_0")]
124    #[allow(clippy::missing_errors_doc)]
125    pub fn from_preset(preset: SCStreamConfigurationPreset) -> crate::error::SCResult<Self> {
126        let ptr = unsafe { crate::ffi::sc_stream_configuration_create_with_preset(preset as i32) };
127        if ptr.is_null() {
128            #[cfg(feature = "macos_26_0")]
129            let required_version = match preset {
130                SCStreamConfigurationPreset::CaptureHDRRecordingPreservedSDRHDR10 => "26.0",
131                _ => "15.0",
132            };
133            #[cfg(not(feature = "macos_26_0"))]
134            let required_version = "15.0";
135            return Err(crate::error::SCError::feature_not_available(
136                format!("SCStreamConfiguration preset {preset:?}"),
137                required_version,
138            ));
139        }
140        Ok(unsafe { Self::from_ptr(ptr) })
141    }
142
143    #[cfg(feature = "macos_15_0")]
144    pub(crate) unsafe fn from_ptr(ptr: *const std::ffi::c_void) -> Self {
145        Self(ptr)
146    }
147}
148
149#[cfg(all(test, feature = "macos_15_0"))]
150mod tests {
151    #[test]
152    fn bridge_refuses_unknown_presets() {
153        for raw in [5, -1, i32::MAX, i32::MIN] {
154            let ptr = unsafe { crate::ffi::sc_stream_configuration_create_with_preset(raw) };
155            assert!(
156                ptr.is_null(),
157                "the bridge built a configuration for preset {raw}"
158            );
159        }
160    }
161}