use std::fmt::Debug;
use std::{error::Error, fmt::Display};
use crate::platform::platform_impl::{ImplAudioCaptureConfig, ImplCaptureAccessToken, ImplCaptureConfig, ImplCaptureStream};
use crate::capturable_content::Capturable;
use crate::prelude::{AudioChannelCount, AudioFrame, AudioSampleRate, CapturableDisplay, CapturableWindow, VideoFrame};
use crate::util::Size;
#[derive(Debug)]
pub enum StreamEvent {
Audio(AudioFrame),
Video(VideoFrame),
Idle,
End,
}
#[derive(Debug, Clone)]
pub enum StreamError {
Other(String),
}
impl Display for StreamError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Other(message) => f.write_fmt(format_args!("StreamError::Other(\"{}\")", message))
}
}
}
impl Error for StreamError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
None
}
fn description(&self) -> &str {
"description() is deprecated; use Display"
}
fn cause(&self) -> Option<&dyn Error> {
self.source()
}
}
#[derive(Debug, Clone)]
pub enum StreamCreateError {
Other(String),
UnsupportedPixelFormat,
UnauthorizedFeature(String),
}
unsafe impl Send for StreamCreateError {}
unsafe impl Sync for StreamCreateError {}
impl Display for StreamCreateError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Other(message) => f.write_fmt(format_args!("StreamCreateError::Other(\"{}\")", message)),
Self::UnsupportedPixelFormat => f.write_fmt(format_args!("StreamCreateError::UnsupportedPixelFormat")),
Self::UnauthorizedFeature(feature) => f.write_fmt(format_args!("StreamCreateError::UnauthorizedFeature({})", feature)),
}
}
}
impl Error for StreamCreateError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
None
}
fn description(&self) -> &str {
"description() is deprecated; use Display"
}
fn cause(&self) -> Option<&dyn Error> {
self.source()
}
}
#[derive(Debug)]
pub enum StreamStopError {
Other(String),
AlreadyStopped,
}
unsafe impl Send for StreamStopError {}
unsafe impl Sync for StreamStopError {}
impl Display for StreamStopError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Other(message) => f.write_fmt(format_args!("StreamStopError::Other(\"{}\")", message)),
Self::AlreadyStopped => f.write_fmt(format_args!("StreamStopError::AlreadyStopped")),
}
}
}
impl Error for StreamStopError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
None
}
fn description(&self) -> &str {
"description() is deprecated; use Display"
}
fn cause(&self) -> Option<&dyn Error> {
self.source()
}
}
#[derive(Clone, Debug)]
#[allow(unused)]
pub struct AudioCaptureConfig {
pub(crate) sample_rate: AudioSampleRate,
pub(crate) channel_count: AudioChannelCount,
pub(crate) impl_capture_audio_config: ImplAudioCaptureConfig,
}
impl AudioCaptureConfig {
pub fn new() -> Self {
Self {
sample_rate: AudioSampleRate::Hz24000,
channel_count: AudioChannelCount::Mono,
impl_capture_audio_config: ImplAudioCaptureConfig::new()
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum CapturePixelFormat {
Bgra8888,
Argb2101010,
V420,
F420,
}
#[derive(Clone, Debug)]
pub struct CaptureConfig {
pub(crate) target: Capturable,
pub(crate) output_size: Size,
pub(crate) show_cursor: bool,
pub(crate) pixel_format: CapturePixelFormat,
pub(crate) capture_audio: Option<AudioCaptureConfig>,
pub(crate) impl_capture_config: ImplCaptureConfig,
pub(crate) buffer_count: usize,
}
#[derive(Debug, Clone)]
pub enum CaptureConfigError {
UnsupportedPixelFormat,
InvalidBufferCount,
}
unsafe impl Send for CaptureConfigError {}
unsafe impl Sync for CaptureConfigError {}
impl Display for CaptureConfigError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::UnsupportedPixelFormat => f.write_fmt(format_args!("CaptureConfigError::UnsupportedPixelFormat")),
Self::InvalidBufferCount => f.write_fmt(format_args!("CaptureConfigError::InvalidBufferCount")),
}
}
}
impl Error for CaptureConfigError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
None
}
fn description(&self) -> &str {
"description() is deprecated; use Display"
}
fn cause(&self) -> Option<&dyn Error> {
self.source()
}
}
impl CaptureConfig {
pub fn with_window(window: CapturableWindow, pixel_format: CapturePixelFormat) -> Result<CaptureConfig, CaptureConfigError> {
let rect = window.rect();
Ok(CaptureConfig {
target: Capturable::Window(window),
pixel_format,
output_size: rect.size,
show_cursor: false,
impl_capture_config: ImplCaptureConfig::new(),
capture_audio: None,
buffer_count: 3,
})
}
pub fn with_display(display: CapturableDisplay, pixel_format: CapturePixelFormat) -> CaptureConfig {
let rect = display.rect();
CaptureConfig {
target: Capturable::Display(display),
pixel_format,
output_size: rect.size,
show_cursor: false,
impl_capture_config: ImplCaptureConfig::new(),
capture_audio: None,
buffer_count: 3,
}
}
pub fn with_buffer_count(self, buffer_count: usize) -> Self {
Self {
buffer_count,
..self
}
}
pub fn with_show_cursor(self, show_cursor: bool) -> Self {
Self {
show_cursor,
..self
}
}
pub fn with_output_size(self, output_size: Size) -> Self {
Self {
output_size,
..self
}
}
}
pub struct CaptureStream {
pub(crate) impl_capture_stream: ImplCaptureStream,
}
unsafe impl Send for CaptureStream {}
#[derive(Clone, Copy, Debug)]
pub struct CaptureAccessToken {
pub(crate) impl_capture_access_token: ImplCaptureAccessToken
}
unsafe impl Send for CaptureAccessToken {}
unsafe impl Sync for CaptureAccessToken {}
impl CaptureAccessToken {
pub fn allows_borderless(&self) -> bool {
self.impl_capture_access_token.allows_borderless()
}
}
impl CaptureStream {
pub fn test_access(borderless: bool) -> Option<CaptureAccessToken> {
ImplCaptureStream::check_access(borderless).map(|impl_capture_access_token|
CaptureAccessToken {
impl_capture_access_token
}
)
}
pub async fn request_access(borderless: bool) -> Option<CaptureAccessToken> {
ImplCaptureStream::request_access(borderless).await.map(|impl_capture_access_token|
CaptureAccessToken {
impl_capture_access_token
}
)
}
pub fn supported_pixel_formats() -> &'static [CapturePixelFormat] {
ImplCaptureStream::supported_pixel_formats()
}
pub fn new(token: CaptureAccessToken, config: CaptureConfig, callback: impl FnMut(Result<StreamEvent, StreamError>) + Send + 'static) -> Result<Self, StreamCreateError> {
let boxed_callback = Box::new(callback);
Ok(Self {
impl_capture_stream: ImplCaptureStream::new(token.impl_capture_access_token, config, boxed_callback)?
})
}
pub fn stop(&mut self) -> Result<(), StreamStopError> {
self.impl_capture_stream.stop()
}
}