pub mod engine;
use std::{error::Error, sync::mpsc};
use anyhow::anyhow;
use engine::ChannelItem;
use crate::{
frame::{Frame, FrameType},
has_permission, is_supported,
targets::Target,
};
pub use engine::get_output_frame_size;
#[derive(Debug, Clone, Copy, Default)]
pub enum Resolution {
_480p, _720p, _1080p, _1440p, _2160p, _4320p,
#[default]
Captured, }
impl Resolution {
#[allow(dead_code)]
fn value(&self, aspect_ratio: f32) -> [u32; 2] {
match *self {
Resolution::_480p => [640, (640_f32 / aspect_ratio).floor() as u32],
Resolution::_720p => [1280, (1280_f32 / aspect_ratio).floor() as u32],
Resolution::_1080p => [1920, (1920_f32 / aspect_ratio).floor() as u32],
Resolution::_1440p => [2560, (2560_f32 / aspect_ratio).floor() as u32],
Resolution::_2160p => [3840, (3840_f32 / aspect_ratio).floor() as u32],
Resolution::_4320p => [7680, (7680_f32 / aspect_ratio).floor() as u32],
Resolution::Captured => {
panic!("不应在 Captured 分辨率类型上调用 .value 方法")
}
}
}
}
#[derive(Debug, Default, Clone)]
pub struct Point {
pub x: f64, pub y: f64, }
#[derive(Debug, Default, Clone)]
pub struct Size {
pub width: f64, pub height: f64, }
#[derive(Debug, Default, Clone)]
pub struct Area {
pub origin: Point, pub size: Size, }
#[derive(Debug, Default, Clone)]
pub struct Options {
pub fps: u32, pub show_cursor: bool, pub show_highlight: bool, pub target: Option<Target>, pub crop_area: Option<Area>, pub output_type: FrameType, pub output_resolution: Resolution, pub excluded_targets: Option<Vec<Target>>, }
pub struct Capturer {
engine: engine::Engine, rx: mpsc::Receiver<anyhow::Result<ChannelItem>>, }
#[derive(Debug)]
pub enum CapturerBuildError {
NotSupported, PermissionNotGranted, }
impl std::fmt::Display for CapturerBuildError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
CapturerBuildError::NotSupported => write!(f, "屏幕捕获不支持"),
CapturerBuildError::PermissionNotGranted => {
write!(f, "未获得屏幕捕获权限")
}
}
}
}
impl Error for CapturerBuildError {}
impl Capturer {
#[deprecated(since = "0.0.6", note = "请使用 `build` 方法创建新的捕获器实例。")]
pub fn new(options: Options) -> anyhow::Result<Capturer> {
let (tx, rx) = mpsc::channel();
let engine = engine::Engine::new(&options, tx)?;
Ok(Capturer { engine, rx })
}
pub fn build(options: Options) -> anyhow::Result<Capturer> {
if !is_supported() {
return Err(anyhow!(CapturerBuildError::NotSupported));
}
if !has_permission() {
return Err(anyhow!(CapturerBuildError::PermissionNotGranted));
}
let (tx, rx) = mpsc::channel();
let engine = engine::Engine::new(&options, tx)?;
Ok(Capturer { engine, rx })
}
pub fn start_capture(&mut self) {
self.engine.start();
}
pub fn stop_capture(&mut self) {
self.engine.stop();
}
pub fn get_next_frame(&self) -> anyhow::Result<Frame> {
loop {
let res = self.rx.recv()??;
if let Some(frame) = self.engine.process_channel_item(res) {
return Ok(frame);
}
}
}
pub fn get_output_frame_size(&mut self) -> [u32; 2] {
self.engine.get_output_frame_size()
}
pub fn raw(&self) -> RawCapturer<'_> {
RawCapturer { capturer: self }
}
pub fn target(&self) -> Option<&Target> {
self.engine.target()
}
}
pub struct RawCapturer<'a> {
#[allow(dead_code)] capturer: &'a Capturer, }