use crate::camera::{
CameraCapture, CameraCaptureConfig, CaptureOutputPreference as CameraOutputPreference,
};
use crate::desktop::{
CaptureOutputPreference as DesktopOutputPreference, DesktopCaptureSource, DesktopVideoCapture,
DesktopVideoCaptureConfig,
};
use crate::{CaptureError, DeviceKind, PermissionState, Select, Support, Unavailable};
use mediaway_common::{NativeHandle, Rational};
use crate::linux::camera::{self, LinuxCameraCapture};
use crate::linux::mic;
use crate::linux::portal;
use crate::linux::screencast::LinuxScreenCapture;
use crate::linux::window::LinuxWindowCapture;
#[must_use]
pub fn support(kind: DeviceKind) -> Support {
match kind {
DeviceKind::Screen | DeviceKind::Window => screencast_portal_support(),
DeviceKind::Camera => camera_support(),
DeviceKind::Microphone => microphone_support(),
_ => Support::Unavailable(Unavailable::NotImplemented),
}
}
fn screencast_portal_support() -> Support {
if portal::probe_screencast().is_ok() {
Support::Supported
} else {
Support::Unavailable(Unavailable::NoDeviceFound)
}
}
fn camera_support() -> Support {
if camera::enumerate_camera_paths().is_empty() {
Support::Unavailable(Unavailable::NoDeviceFound)
} else {
Support::Supported
}
}
fn microphone_support() -> Support {
if mic::probe_daemon_reachable() {
Support::Supported
} else {
Support::Unavailable(Unavailable::NoDeviceFound)
}
}
pub fn request_permission(kind: DeviceKind) -> Result<PermissionState, CaptureError> {
if matches!(support(kind), Support::Unavailable(_)) {
return Ok(PermissionState::NotSupported);
}
match kind {
DeviceKind::Screen => probe_screen_permission(),
DeviceKind::Window => probe_window_permission(),
DeviceKind::Camera => probe_camera_permission(),
DeviceKind::Microphone => Ok(PermissionState::Granted),
_ => Ok(PermissionState::NotSupported),
}
}
fn probe_screen_permission() -> Result<PermissionState, CaptureError> {
let cfg = DesktopVideoCaptureConfig {
source: DesktopCaptureSource::Screen {
select: Select::Default,
},
time_base: Rational::new(1, 30),
output: DesktopOutputPreference::CpuFramesOk,
gpu_device: None,
};
match LinuxScreenCapture::open(&cfg) {
Ok(mut cap) => {
let _ = cap.close();
Ok(PermissionState::Granted)
}
Err(CaptureError::AccessDenied) => Ok(PermissionState::Denied),
Err(CaptureError::Unsupported) => Ok(PermissionState::Unknown),
Err(e) => Err(e),
}
}
fn probe_window_permission() -> Result<PermissionState, CaptureError> {
let window = NativeHandle::new(1).ok_or(CaptureError::InvalidInput)?;
let cfg = DesktopVideoCaptureConfig {
source: DesktopCaptureSource::Window { window },
time_base: Rational::new(1, 30),
output: DesktopOutputPreference::CpuFramesOk,
gpu_device: None,
};
match LinuxWindowCapture::open(&cfg) {
Ok(mut cap) => {
let _ = cap.close();
Ok(PermissionState::Granted)
}
Err(CaptureError::AccessDenied) => Ok(PermissionState::Denied),
Err(CaptureError::Unsupported) => Ok(PermissionState::Unknown),
Err(e) => Err(e),
}
}
fn probe_camera_permission() -> Result<PermissionState, CaptureError> {
let cfg = CameraCaptureConfig {
select: Select::Default,
time_base: Rational::new(1, 30),
output: CameraOutputPreference::CpuFramesOk,
gpu_device: None,
};
match LinuxCameraCapture::open(&cfg) {
Ok(mut cap) => {
let _ = cap.close();
Ok(PermissionState::Granted)
}
Err(CaptureError::AccessDenied) => Ok(PermissionState::Denied),
Err(CaptureError::Unsupported | CaptureError::InvalidInput) => Ok(PermissionState::Unknown),
Err(e) => Err(e),
}
}
#[cfg(test)]
#[path = "capabilities_tests.rs"]
mod tests;