diff --git a/src/backends/capture/avfoundation.rs b/src/backends/capture/avfoundation.rs index bcb1072..27af536 100644 --- a/src/backends/capture/avfoundation.rs +++ b/src/backends/capture/avfoundation.rs @@ -15,6 +15,11 @@ use nokhwa_bindings_macos::avfoundation::{ }; use std::{any::Any, borrow::Cow, collections::HashMap}; +/// The backend struct that interfaces with V4L2. +/// To see what this does, please see [`CaptureBackendTrait`]. +/// # Quirks +/// - While working with `iOS` is allowed, it is not officially supported and may not work. +/// - You **must** call [`nokhwa_initialize`](crate::nokhwa_initialize) **before** doing anything with `AVFoundation`. pub struct AVFoundationCaptureDevice { device: AVCaptureDevice, dev_input: Option, @@ -26,6 +31,11 @@ pub struct AVFoundationCaptureDevice { } impl AVFoundationCaptureDevice { + /// Creates a new capture device using the `AVFoundation` backend. Indexes are gives to devices by the OS, and usually numbered by order of discovery. + /// + /// If `camera_format` is `None`, it will be spawned with with 640x480@15 FPS, MJPEG [`CameraFormat`] default. + /// # Errors + /// This function will error if the camera is currently busy or if `AVFoundation` can't read device information, or permission was not given by the user. pub fn new(index: usize, camera_format: Option) -> Result { let camera_format = match camera_format { Some(fmt) => fmt, @@ -57,6 +67,10 @@ impl AVFoundationCaptureDevice { }) } + /// Creates a new capture device using the `AVFoundation` backend with desired settings. + /// + /// # Errors + /// This function will error if the camera is currently busy or if `AVFoundation` can't read device information, or permission was not given by the user. pub fn new_with( index: usize, width: u32, @@ -88,6 +102,8 @@ impl CaptureBackendTrait for AVFoundationCaptureDevice { Ok(()) } + #[allow(clippy::cast_possible_truncation)] + #[allow(clippy::cast_sign_loss)] fn compatible_list_by_resolution( &mut self, fourcc: FrameFormat, @@ -101,7 +117,7 @@ impl CaptureBackendTrait for AVFoundationCaptureDevice { FrameFormat::from(fmt.fourcc), Resolution::from(fmt.resolution), (&fmt.fps_list) - .into_iter() + .iter() .map(|f| *f as u32) .collect::>(), ) @@ -279,7 +295,7 @@ impl CaptureBackendTrait for AVFoundationCaptureDevice { impl Drop for AVFoundationCaptureDevice { fn drop(&mut self) { - let _ = self.stop_stream(); + if self.stop_stream().is_err() {} self.device.unlock(); } } diff --git a/src/backends/capture/v4l2.rs b/src/backends/capture/v4l2.rs index 9f5d786..9b7ea9f 100644 --- a/src/backends/capture/v4l2.rs +++ b/src/backends/capture/v4l2.rs @@ -166,11 +166,11 @@ pub struct V4LCaptureDevice<'a> { } impl<'a> V4LCaptureDevice<'a> { - /// Creates a new capture device using the V4L2 backend. Indexes are gives to devices by the OS, and usually numbered by order of discovery. + /// Creates a new capture device using the `V4L2` backend. Indexes are gives to devices by the OS, and usually numbered by order of discovery. /// /// If `camera_format` is `None`, it will be spawned with with 640x480@15 FPS, MJPEG [`CameraFormat`] default. /// # Errors - /// This function will error if the camera is currently busy or if V4L2 can't read device information. + /// This function will error if the camera is currently busy or if `V4L2` can't read device information. pub fn new(index: usize, cam_fmt: Option) -> Result { let device = match Device::new(index) { Ok(dev) => dev, @@ -254,9 +254,9 @@ impl<'a> V4LCaptureDevice<'a> { }) } - /// Create a new V4L Camera with desired settings. + /// Create a new `V4L2` Camera with desired settings. /// # Errors - /// This function will error if the camera is currently busy or if V4L2 can't read device information. + /// This function will error if the camera is currently busy or if `V4L2` can't read device information. pub fn new_with( index: usize, width: u32, diff --git a/src/init.rs b/src/init.rs index 8babd10..2c3162b 100644 --- a/src/init.rs +++ b/src/init.rs @@ -1,29 +1,32 @@ -use crate::NokhwaError; +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ #[cfg(not(all( feature = "input-avfoundation", any(target_os = "macos", target_os = "ios") )))] -pub fn init_avfoundation(_: fn(bool)) -> Result<(), NokhwaError> { - Ok(()) +fn init_avfoundation(callback: fn(bool)) { + callback(true); } #[cfg(all( feature = "input-avfoundation", any(target_os = "macos", target_os = "ios") ))] -pub fn init_avfoundation(callback: fn(bool)) -> Result<(), NokhwaError> { +fn init_avfoundation(callback: fn(bool)) { use nokhwa_bindings_macos::avfoundation::request_permission_with_callback; request_permission_with_callback(callback); - Ok(()) } #[cfg(not(all( feature = "input-avfoundation", any(target_os = "macos", target_os = "ios") )))] -pub fn status_avfoundation() -> bool { +fn status_avfoundation() -> bool { true } @@ -31,13 +34,29 @@ pub fn status_avfoundation() -> bool { feature = "input-avfoundation", any(target_os = "macos", target_os = "ios") ))] -pub fn status_avfoundation() -> bool { +fn status_avfoundation() -> bool { use nokhwa_bindings_macos::avfoundation::{ current_authorization_status, AVAuthorizationStatus, }; - match current_authorization_status() { - AVAuthorizationStatus::Authorized => true, - _ => false, - } + matches!( + current_authorization_status(), + AVAuthorizationStatus::Authorized + ) +} + +/// Initialize `nokhwa` +/// It is your responsibility to call this function before anything else, but only on `MacOS`. +/// +/// The `on_complete` is called after initialization (a.k.a User granted permission). The callback's argument +/// is weather the initialization was successful or not +pub fn nokhwa_initialize(on_complete: fn(bool)) { + init_avfoundation(on_complete); +} + +/// Check the status if `nokhwa` +/// True if the initialization is successful (ready-to-use) +#[must_use] +pub fn nokhwa_check() -> bool { + status_avfoundation() } diff --git a/src/query.rs b/src/query.rs index 7804461..0cd093b 100644 --- a/src/query.rs +++ b/src/query.rs @@ -86,7 +86,7 @@ pub fn query_devices(api: CaptureAPIBackend) -> Result, NokhwaEr CaptureAPIBackend::UniversalVideoClass => query_uvc(), CaptureAPIBackend::MediaFoundation => query_msmf(), CaptureAPIBackend::GStreamer => query_gstreamer(), - _ => Err(NokhwaError::UnsupportedOperationError(api)), + CaptureAPIBackend::OpenCv => Err(NokhwaError::UnsupportedOperationError(api)), } } @@ -293,19 +293,19 @@ fn query_msmf() -> Result, NokhwaError> { fn query_avfoundation() -> Result, NokhwaError> { use nokhwa_bindings_macos::avfoundation::AVCaptureDeviceDiscoverySession; - Ok( - AVCaptureDeviceDiscoverySession::default()? - .devices() - .into_iter() - .map(|device| CameraInfo::from(device)) - .collect() - ) + Ok(AVCaptureDeviceDiscoverySession::default()? + .devices() + .into_iter() + .map(CameraInfo::from) + .collect()) } #[cfg(not(all( -feature = "input-avfoundation", -any(target_os = "macos", target_os = "ios") + feature = "input-avfoundation", + any(target_os = "macos", target_os = "ios") )))] fn query_avfoundation() -> Result, NokhwaError> { - Err(NokhwaError::UnsupportedOperationError(CaptureAPIBackend::AVFoundation)) + Err(NokhwaError::UnsupportedOperationError( + CaptureAPIBackend::AVFoundation, + )) } diff --git a/src/utils.rs b/src/utils.rs index 89413be..a7ef2a6 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -94,9 +94,9 @@ impl From for FrameFormat { feature = "input-avfoundation", any(target_os = "macos", target_os = "ios") ))] -impl Into for FrameFormat { - fn into(self) -> AVFourCC { - match self { +impl From for AVFourCC { + fn from(ff: FrameFormat) -> Self { + match ff { FrameFormat::MJPEG => AVFourCC::MJPEG, FrameFormat::YUYV => AVFourCC::YUV2, } @@ -208,6 +208,7 @@ impl From for MFResolution { feature = "input-avfoundation", any(target_os = "macos", target_os = "ios") ))] +#[allow(clippy::cast_sign_loss)] impl From for Resolution { fn from(res: AVVideoResolution) -> Self { Resolution { @@ -362,15 +363,17 @@ impl From for Format { feature = "input-avfoundation", any(target_os = "macos", target_os = "ios") ))] -impl Into for CameraFormat { - fn into(self) -> CaptureDeviceFormatDescriptor { +#[allow(clippy::cast_possible_wrap)] +#[allow(clippy::cast_lossless)] +impl From for CaptureDeviceFormatDescriptor { + fn from(cf: CameraFormat) -> Self { CaptureDeviceFormatDescriptor { resolution: AVVideoResolution { - width: self.width() as i32, - height: self.height() as i32, + width: cf.width() as i32, + height: cf.height() as i32, }, - fps: self.frame_rate() as f64, - fourcc: self.format().into(), + fps: cf.frame_rate() as f64, + fourcc: cf.format().into(), } } } @@ -518,6 +521,7 @@ impl From> for CameraInfo { feature = "input-avfoundation", any(target_os = "macos", target_os = "ios") ))] +#[allow(clippy::cast_possible_truncation)] impl From for CameraInfo { fn from(descriptor: AVCaptureDeviceDescriptor) -> Self { CameraInfo {