use crate::utils::{
ffi_string::{ffi_string_from_buffer, SMALL_BUFFER_SIZE},
four_char_code::FourCharCode,
};
const DEFAULT_ALPHA: f32 = 1.0;
type BackgroundColor = (f32, f32, f32, f32);
use super::{internal::SCStreamConfiguration, pixel_format::PixelFormat};
pub mod color_matrix {
pub const ITU_R_709_2: &str = "ITU_R_709_2";
pub const ITU_R_601_4: &str = "ITU_R_601_4";
pub const SMPTE_240M_1995: &str = "SMPTE_240M_1995";
}
pub mod color_space {
pub const SRGB: &str = "kCGColorSpaceSRGB";
pub const DISPLAY_P3: &str = "kCGColorSpaceDisplayP3";
pub const EXTENDED_LINEAR_DISPLAY_P3: &str = "kCGColorSpaceExtendedLinearDisplayP3";
pub const EXTENDED_LINEAR_SRGB: &str = "kCGColorSpaceExtendedLinearSRGB";
pub const ITUR_2100_PQ: &str = "kCGColorSpaceITUR_2100_PQ";
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct InteriorNulError;
impl std::fmt::Display for InteriorNulError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("value contains an interior NUL byte and cannot cross the C boundary")
}
}
impl std::error::Error for InteriorNulError {}
impl SCStreamConfiguration {
pub fn set_pixel_format(&mut self, pixel_format: PixelFormat) -> &mut Self {
let four_char_code: FourCharCode = pixel_format.into();
unsafe {
crate::ffi::sc_stream_configuration_set_pixel_format(
self.as_ptr(),
four_char_code.as_u32(),
);
}
self
}
#[must_use]
pub fn with_pixel_format(mut self, pixel_format: PixelFormat) -> Self {
self.set_pixel_format(pixel_format);
self
}
pub fn pixel_format(&self) -> PixelFormat {
unsafe {
let value = crate::ffi::sc_stream_configuration_get_pixel_format(self.as_ptr());
PixelFormat::from(value)
}
}
pub fn set_background_color_rgba(&mut self, r: f32, g: f32, b: f32, a: f32) -> &mut Self {
unsafe {
crate::ffi::sc_stream_configuration_set_background_color(self.as_ptr(), r, g, b, a);
}
self
}
pub fn set_background_color(&mut self, r: f32, g: f32, b: f32) -> &mut Self {
self.set_background_color_rgba(r, g, b, DEFAULT_ALPHA)
}
#[must_use]
pub fn with_background_color_rgba(mut self, r: f32, g: f32, b: f32, a: f32) -> Self {
self.set_background_color_rgba(r, g, b, a);
self
}
#[must_use]
pub fn with_background_color(mut self, r: f32, g: f32, b: f32) -> Self {
self.set_background_color(r, g, b);
self
}
pub fn background_color(&self) -> Option<BackgroundColor> {
let mut r = 0.0f32;
let mut g = 0.0f32;
let mut b = 0.0f32;
let mut a = 0.0f32;
let was_set = unsafe {
crate::ffi::sc_stream_configuration_get_background_color(
self.as_ptr(),
&mut r,
&mut g,
&mut b,
&mut a,
)
};
was_set.then_some((r, g, b, a))
}
pub fn set_color_space_name(&mut self, name: &str) -> &mut Self {
let _ = self.try_set_color_space_name(name);
self
}
pub fn try_set_color_space_name(&mut self, name: &str) -> Result<&mut Self, InteriorNulError> {
let c_name = std::ffi::CString::new(name).map_err(|_| InteriorNulError)?;
unsafe {
crate::ffi::sc_stream_configuration_set_color_space_name(
self.as_ptr(),
c_name.as_ptr(),
);
}
Ok(self)
}
#[must_use]
pub fn with_color_space_name(mut self, name: &str) -> Self {
self.set_color_space_name(name);
self
}
pub fn color_space_name(&self) -> Option<String> {
unsafe {
ffi_string_from_buffer(SMALL_BUFFER_SIZE, |buf, len| {
crate::ffi::sc_stream_configuration_get_color_space_name(self.as_ptr(), buf, len)
})
}
}
pub fn set_color_matrix(&mut self, matrix: &str) -> &mut Self {
let _ = self.try_set_color_matrix(matrix);
self
}
pub fn try_set_color_matrix(&mut self, matrix: &str) -> Result<&mut Self, InteriorNulError> {
let c_matrix = std::ffi::CString::new(matrix).map_err(|_| InteriorNulError)?;
unsafe {
crate::ffi::sc_stream_configuration_set_color_matrix(self.as_ptr(), c_matrix.as_ptr());
}
Ok(self)
}
pub fn color_matrix(&self) -> Option<String> {
unsafe {
ffi_string_from_buffer(SMALL_BUFFER_SIZE, |buf, len| {
crate::ffi::sc_stream_configuration_get_color_matrix(self.as_ptr(), buf, len)
})
}
}
#[must_use]
pub fn with_color_matrix(mut self, matrix: &str) -> Self {
self.set_color_matrix(matrix);
self
}
}