2022-07-21 20:04:39 +08:00
|
|
|
use crate::common::{x11::Frame, TraitCapturer};
|
2021-07-23 17:52:38 +08:00
|
|
|
use crate::wayland::{capturable::*, *};
|
2022-10-11 20:36:19 -07:00
|
|
|
use std::{io, sync::RwLock, time::Duration};
|
2021-07-23 17:52:38 +08:00
|
|
|
|
|
|
|
pub struct Capturer(Display, Box<dyn Recorder>, bool, Vec<u8>);
|
|
|
|
|
2023-01-05 14:58:38 +08:00
|
|
|
pub const IS_CURSOR_EMBEDDED: bool = true;
|
2022-11-29 16:36:35 +08:00
|
|
|
|
2022-10-11 20:36:19 -07:00
|
|
|
lazy_static::lazy_static! {
|
|
|
|
static ref MAP_ERR: RwLock<Option<fn(err: String)-> io::Error>> = Default::default();
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn set_map_err(f: fn(err: String) -> io::Error) {
|
|
|
|
*MAP_ERR.write().unwrap() = Some(f);
|
|
|
|
}
|
|
|
|
|
2021-07-23 17:52:38 +08:00
|
|
|
fn map_err<E: ToString>(err: E) -> io::Error {
|
2022-10-11 20:36:19 -07:00
|
|
|
if let Some(f) = *MAP_ERR.read().unwrap() {
|
|
|
|
f(err.to_string())
|
|
|
|
} else {
|
|
|
|
io::Error::new(io::ErrorKind::Other, err.to_string())
|
|
|
|
}
|
2021-07-23 17:52:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Capturer {
|
|
|
|
pub fn new(display: Display, yuv: bool) -> io::Result<Capturer> {
|
|
|
|
let r = display.0.recorder(false).map_err(map_err)?;
|
|
|
|
Ok(Capturer(display, r, yuv, Default::default()))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn width(&self) -> usize {
|
|
|
|
self.0.width()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn height(&self) -> usize {
|
|
|
|
self.0.height()
|
|
|
|
}
|
2022-07-21 20:04:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
impl TraitCapturer for Capturer {
|
|
|
|
fn set_use_yuv(&mut self, use_yuv: bool) {
|
|
|
|
self.2 = use_yuv;
|
|
|
|
}
|
2021-07-23 17:52:38 +08:00
|
|
|
|
2022-07-21 20:04:39 +08:00
|
|
|
fn frame<'a>(&'a mut self, timeout: Duration) -> io::Result<Frame<'a>> {
|
2022-07-07 01:27:21 +08:00
|
|
|
match self.1.capture(timeout.as_millis() as _).map_err(map_err)? {
|
2021-07-23 17:52:38 +08:00
|
|
|
PixelProvider::BGR0(w, h, x) => Ok(Frame(if self.2 {
|
|
|
|
crate::common::bgra_to_i420(w as _, h as _, &x, &mut self.3);
|
|
|
|
&self.3[..]
|
|
|
|
} else {
|
|
|
|
x
|
|
|
|
})),
|
2022-12-21 04:12:34 +09:00
|
|
|
PixelProvider::RGB0(w, h, x) => Ok(Frame(if self.2 {
|
|
|
|
crate::common::rgba_to_i420(w as _, h as _, &x, &mut self.3);
|
|
|
|
&self.3[..]
|
|
|
|
} else {
|
|
|
|
x
|
|
|
|
})),
|
2021-07-23 17:52:38 +08:00
|
|
|
PixelProvider::NONE => Err(std::io::ErrorKind::WouldBlock.into()),
|
|
|
|
_ => Err(map_err("Invalid data")),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct Display(pipewire::PipeWireCapturable);
|
|
|
|
|
|
|
|
impl Display {
|
|
|
|
pub fn primary() -> io::Result<Display> {
|
|
|
|
let mut all = Display::all()?;
|
|
|
|
if all.is_empty() {
|
|
|
|
return Err(io::ErrorKind::NotFound.into());
|
|
|
|
}
|
|
|
|
Ok(all.remove(0))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn all() -> io::Result<Vec<Display>> {
|
2022-11-29 16:36:35 +08:00
|
|
|
Ok(pipewire::get_capturables(true)
|
2021-07-23 17:52:38 +08:00
|
|
|
.map_err(map_err)?
|
|
|
|
.drain(..)
|
|
|
|
.map(|x| Display(x))
|
|
|
|
.collect())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn width(&self) -> usize {
|
|
|
|
self.0.size.0
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn height(&self) -> usize {
|
|
|
|
self.0.size.1
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn origin(&self) -> (i32, i32) {
|
|
|
|
self.0.position
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_online(&self) -> bool {
|
|
|
|
true
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_primary(&self) -> bool {
|
|
|
|
false
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn name(&self) -> String {
|
|
|
|
"".to_owned()
|
|
|
|
}
|
|
|
|
}
|