use crate::imp::desktop_capturer as imp_dc;
pub struct DesktopCapturerOptions {
sys_handle: imp_dc::DesktopCapturerOptions,
}
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum DesktopCaptureSourceType {
Screen,
Window,
#[cfg(any(target_os = "macos", target_os = "linux"))]
Generic,
}
impl DesktopCapturerOptions {
pub fn new(source_type: DesktopCaptureSourceType) -> Self {
let source_type = match source_type {
DesktopCaptureSourceType::Screen => imp_dc::SourceType::Screen,
DesktopCaptureSourceType::Window => imp_dc::SourceType::Window,
#[cfg(any(target_os = "macos", target_os = "linux"))]
DesktopCaptureSourceType::Generic => imp_dc::SourceType::Generic,
};
Self { sys_handle: imp_dc::DesktopCapturerOptions::new(source_type) }
}
pub fn set_include_cursor(&mut self, include: bool) {
self.sys_handle = self.sys_handle.with_cursor(include);
}
#[cfg(target_os = "macos")]
pub fn set_sck_system_picker(&mut self, allow_sck_system_picker: bool) {
self.sys_handle = self.sys_handle.with_sck_system_picker(allow_sck_system_picker);
}
}
pub struct DesktopCapturer {
handle: imp_dc::DesktopCapturer,
}
impl DesktopCapturer {
pub fn new(options: DesktopCapturerOptions) -> Option<Self> {
let desktop_capturer = imp_dc::DesktopCapturer::new(options.sys_handle);
if desktop_capturer.is_none() {
return None;
}
Some(Self { handle: desktop_capturer.unwrap() })
}
pub fn start_capture<T>(&mut self, source: Option<CaptureSource>, mut callback: T)
where
T: FnMut(Result<DesktopFrame, CaptureError>) + Send + 'static,
{
if let Some(source) = source {
self.handle.select_source(source.sys_handle.id());
}
let inner_callback = move |result: Result<imp_dc::DesktopFrame, imp_dc::CaptureError>| {
callback(capture_result_from_sys(result));
};
self.handle.start(inner_callback);
}
pub fn capture_frame(&mut self) {
self.handle.capture_frame();
}
pub fn get_source_list(&self) -> Vec<CaptureSource> {
let source_list = self.handle.get_source_list();
source_list.into_iter().map(|source| CaptureSource { sys_handle: source }).collect()
}
}
pub struct DesktopFrame {
sys_handle: imp_dc::DesktopFrame,
}
impl DesktopFrame {
fn new(sys_handle: imp_dc::DesktopFrame) -> Self {
Self { sys_handle }
}
pub fn width(&self) -> i32 {
self.sys_handle.width() as i32
}
pub fn height(&self) -> i32 {
self.sys_handle.height() as i32
}
pub fn stride(&self) -> u32 {
self.sys_handle.stride() as u32
}
pub fn left(&self) -> i32 {
self.sys_handle.left()
}
pub fn top(&self) -> i32 {
self.sys_handle.top()
}
pub fn data(&self) -> &[u8] {
self.sys_handle.data()
}
}
#[derive(Clone)]
pub struct CaptureSource {
sys_handle: imp_dc::CaptureSource,
}
impl CaptureSource {
pub fn id(&self) -> u64 {
self.sys_handle.id()
}
pub fn title(&self) -> String {
self.sys_handle.title()
}
pub fn display_id(&self) -> i64 {
self.sys_handle.display_id()
}
}
impl std::fmt::Display for CaptureSource {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("CaptureSource")
.field("id", &self.id())
.field("title", &self.title())
.field("display_id", &self.display_id())
.finish()
}
}
#[derive(Debug, PartialEq)]
pub enum CaptureError {
Temporary,
Permanent,
}
fn capture_result_from_sys(
result: Result<imp_dc::DesktopFrame, imp_dc::CaptureError>,
) -> Result<DesktopFrame, CaptureError> {
match result {
Ok(frame) => Ok(DesktopFrame::new(frame)),
Err(error) => Err(match error {
imp_dc::CaptureError::Temporary => CaptureError::Temporary,
imp_dc::CaptureError::Permanent => CaptureError::Permanent,
}),
}
}