| 
									
										
										
										
											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>);
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-29 16:36:35 +08:00
										 |  |  | pub const IS_CURSOR_EMBEDED: bool = true;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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
 | 
					
						
							|  |  |  |             })),
 | 
					
						
							|  |  |  |             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()
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | }
 |