mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-03-30 00:21:02 +03:00
source code
This commit is contained in:
111
libs/scrap/src/quartz/capturer.rs
Normal file
111
libs/scrap/src/quartz/capturer.rs
Normal file
@@ -0,0 +1,111 @@
|
||||
use std::ptr;
|
||||
|
||||
use block::{Block, ConcreteBlock};
|
||||
use libc::c_void;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use super::config::Config;
|
||||
use super::display::Display;
|
||||
use super::ffi::*;
|
||||
use super::frame::Frame;
|
||||
|
||||
pub struct Capturer {
|
||||
stream: CGDisplayStreamRef,
|
||||
queue: DispatchQueue,
|
||||
|
||||
width: usize,
|
||||
height: usize,
|
||||
format: PixelFormat,
|
||||
display: Display,
|
||||
stopped: Arc<Mutex<bool>>,
|
||||
}
|
||||
|
||||
impl Capturer {
|
||||
pub fn new<F: Fn(Frame) + 'static>(
|
||||
display: Display,
|
||||
width: usize,
|
||||
height: usize,
|
||||
format: PixelFormat,
|
||||
config: Config,
|
||||
handler: F,
|
||||
) -> Result<Capturer, CGError> {
|
||||
let stopped = Arc::new(Mutex::new(false));
|
||||
let cloned_stopped = stopped.clone();
|
||||
let handler: FrameAvailableHandler = ConcreteBlock::new(move |status, _, surface, _| {
|
||||
use self::CGDisplayStreamFrameStatus::*;
|
||||
if status == Stopped {
|
||||
let mut lock = cloned_stopped.lock().unwrap();
|
||||
*lock = true;
|
||||
return;
|
||||
}
|
||||
if status == FrameComplete {
|
||||
handler(unsafe { Frame::new(surface) });
|
||||
}
|
||||
})
|
||||
.copy();
|
||||
|
||||
let queue = unsafe {
|
||||
dispatch_queue_create(
|
||||
b"quadrupleslap.scrap\0".as_ptr() as *const i8,
|
||||
ptr::null_mut(),
|
||||
)
|
||||
};
|
||||
|
||||
let stream = unsafe {
|
||||
let config = config.build();
|
||||
let stream = CGDisplayStreamCreateWithDispatchQueue(
|
||||
display.id(),
|
||||
width,
|
||||
height,
|
||||
format,
|
||||
config,
|
||||
queue,
|
||||
&*handler as *const Block<_, _> as *const c_void,
|
||||
);
|
||||
CFRelease(config);
|
||||
stream
|
||||
};
|
||||
|
||||
match unsafe { CGDisplayStreamStart(stream) } {
|
||||
CGError::Success => Ok(Capturer {
|
||||
stream,
|
||||
queue,
|
||||
width,
|
||||
height,
|
||||
format,
|
||||
display,
|
||||
stopped,
|
||||
}),
|
||||
x => Err(x),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn width(&self) -> usize {
|
||||
self.width
|
||||
}
|
||||
pub fn height(&self) -> usize {
|
||||
self.height
|
||||
}
|
||||
pub fn format(&self) -> PixelFormat {
|
||||
self.format
|
||||
}
|
||||
pub fn display(&self) -> Display {
|
||||
self.display
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Capturer {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
let _ = CGDisplayStreamStop(self.stream);
|
||||
loop {
|
||||
if *self.stopped.lock().unwrap() {
|
||||
break;
|
||||
}
|
||||
std::thread::sleep(std::time::Duration::from_millis(30));
|
||||
}
|
||||
CFRelease(self.stream);
|
||||
dispatch_release(self.queue);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user