Skip to content

Commit 0e2d000

Browse files
committed
New platform API to simply ApiBackend and allow for custom backends on the fly
1 parent 096880e commit 0e2d000

File tree

18 files changed

+215
-197
lines changed

18 files changed

+215
-197
lines changed

nokhwa-bindings-linux/src/v4l2.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use nokhwa_core::properties::{CameraProperties, CameraPropertyFlag, CameraProper
1414
use nokhwa_core::{define_back_and_fourth_control, define_back_and_fourth_frame_format};
1515
use nokhwa_core::error::{NokhwaError, NokhwaResult};
1616
use nokhwa_core::frame_format::FrameFormat;
17-
use nokhwa_core::types::{CameraFormat, CameraIndex, CameraInfo, FrameRate, Resolution};
17+
use nokhwa_core::types::{CameraFormat, CameraIndex, CameraInformation, FrameRate, Resolution};
1818

1919
const NULL_FCC: &'static [u8; 4] = &[0x00, 0x00, 0x00, 0x00];
2020

nokhwa-bindings-macos/src/lib.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ mod internal {
225225
use nokhwa_core::{
226226
error::NokhwaError,
227227
types::{
228-
ApiBackend, CameraFormat, CameraIndex, CameraInfo,
228+
ApiBackend, CameraFormat, CameraIndex, CameraInformation,
229229
FrameFormat,
230230
KnownCameraControlFlag, Resolution,
231231
},
@@ -509,7 +509,7 @@ mod internal {
509509
}
510510

511511
// fuck it, use deprecated APIs
512-
pub fn query_avfoundation() -> Result<Vec<CameraInfo>, NokhwaError> {
512+
pub fn query_avfoundation() -> Result<Vec<CameraInformation>, NokhwaError> {
513513
Ok(AVCaptureDeviceDiscoverySession::new(vec![
514514
AVCaptureDeviceType::UltraWide,
515515
AVCaptureDeviceType::WideAngle,
@@ -520,7 +520,7 @@ mod internal {
520520
.devices())
521521
}
522522

523-
pub fn get_raw_device_info(index: CameraIndex, device: *mut Object) -> CameraInfo {
523+
pub fn get_raw_device_info(index: CameraIndex, device: *mut Object) -> CameraInformation {
524524
let name = nsstr_to_str(unsafe { msg_send![device, localizedName] });
525525
let manufacturer = nsstr_to_str(unsafe { msg_send![device, manufacturer] });
526526
let position: AVCaptureDevicePosition = unsafe { msg_send![device, position] };
@@ -533,7 +533,7 @@ mod internal {
533533
);
534534
let misc = nsstr_to_str(unsafe { msg_send![device, uniqueID] });
535535

536-
CameraInfo::new(name.as_ref(), &description, misc.as_ref(), index)
536+
CameraInformation::new(name.as_ref(), &description, misc.as_ref(), index)
537537
}
538538

539539
#[derive(Copy, Clone, Debug, Hash, Ord, PartialOrd, Eq, PartialEq)]
@@ -818,7 +818,7 @@ mod internal {
818818
])
819819
}
820820

821-
pub fn devices(&self) -> Vec<CameraInfo> {
821+
pub fn devices(&self) -> Vec<CameraInformation> {
822822
let device_ns_array: *mut Object = unsafe { msg_send![self.inner, devices] };
823823
let objects_len: NSUInteger = unsafe { NSArray::count(device_ns_array) };
824824
let mut devices = Vec::with_capacity(objects_len as usize);
@@ -836,7 +836,7 @@ mod internal {
836836

837837
pub struct AVCaptureDevice {
838838
inner: *mut Object,
839-
device: CameraInfo,
839+
device: CameraInformation,
840840
locked: bool,
841841
}
842842

@@ -890,7 +890,7 @@ mod internal {
890890
})
891891
}
892892

893-
pub fn info(&self) -> &CameraInfo {
893+
pub fn info(&self) -> &CameraInformation {
894894
&self.device
895895
}
896896

nokhwa-bindings-windows/src/lib.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
pub mod wmf {
3232
use nokhwa_core::error::NokhwaError;
3333
use nokhwa_core::types::{
34-
ApiBackend, CameraFormat, CameraIndex, CameraInfo,
34+
ApiBackend, CameraFormat, CameraIndex, CameraInformation,
3535
FrameFormat, KnownCameraControlFlag, Resolution,
3636
};
3737
use once_cell::sync::Lazy;
@@ -295,7 +295,7 @@ pub mod wmf {
295295
fn activate_to_descriptors(
296296
index: CameraIndex,
297297
imf_activate: &IMFActivate,
298-
) -> Result<CameraInfo, NokhwaError> {
298+
) -> Result<CameraInformation, NokhwaError> {
299299
let mut pwstr_name = PWSTR(&mut 0_u16);
300300
let mut len_pwstrname = 0;
301301
let mut pwstr_symlink = PWSTR(&mut 0_u16);
@@ -357,15 +357,15 @@ pub mod wmf {
357357
})?
358358
};
359359

360-
Ok(CameraInfo::new(
360+
Ok(CameraInformation::new(
361361
&name,
362362
"MediaFoundation Camera",
363363
&symlink,
364364
index,
365365
))
366366
}
367367

368-
pub fn query_media_foundation_descriptors() -> Result<Vec<CameraInfo>, NokhwaError> {
368+
pub fn query_media_foundation_descriptors() -> Result<Vec<CameraInformation>, NokhwaError> {
369369
let mut device_list = vec![];
370370

371371
for (index, activate_ptr) in query_activate_pointers()?.into_iter().enumerate() {
@@ -421,7 +421,7 @@ pub mod wmf {
421421

422422
pub struct MediaFoundationDevice {
423423
is_open: Cell<bool>,
424-
device_specifier: CameraInfo,
424+
device_specifier: CameraInformation,
425425
device_format: CameraFormat,
426426
source_reader: IMFSourceReader,
427427
}
@@ -1226,7 +1226,7 @@ pub mod wmf {
12261226
pub mod wmf {
12271227
use nokhwa_core::error::NokhwaError;
12281228
use nokhwa_core::types::{
1229-
CameraFormat, CameraIndex, CameraInfo,
1229+
CameraFormat, CameraIndex, CameraInformation,
12301230
};
12311231
use std::borrow::Cow;
12321232
use nokhwa_core::properties::{CameraControl, ControlValue, KnownCameraControl};
@@ -1243,7 +1243,7 @@ pub mod wmf {
12431243
))
12441244
}
12451245

1246-
pub fn query_msmf() -> Result<Vec<CameraInfo>, NokhwaError> {
1246+
pub fn query_msmf() -> Result<Vec<CameraInformation>, NokhwaError> {
12471247
Err(NokhwaError::NotImplementedError(
12481248
"Not on windows".to_string(),
12491249
))

nokhwa-core/src/camera.rs

Lines changed: 27 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,10 @@
1-
use crate::error::{NokhwaError, NokhwaResult};
1+
use crate::error::{NokhwaError};
22
use crate::frame_format::FrameFormat;
33
use crate::properties::{ControlId, ControlValue, Properties};
4-
use crate::types::{CameraFormat, CameraIndex, FrameRate, Resolution};
4+
use crate::types::{CameraFormat, FrameRate, Resolution};
55
use std::collections::HashMap;
6-
use crate::frame_buffer::FrameBuffer;
76
use crate::stream::Stream;
87

9-
pub trait Open {
10-
fn open(index: CameraIndex) -> NokhwaResult<Self> where Self: Sized;
11-
}
12-
13-
#[cfg(feature = "async")]
14-
pub trait AsyncOpen: Sized {
15-
async fn open_async(index: CameraIndex) -> NokhwaResult<Self>;
16-
}
17-
18-
198
pub trait Setting {
209
fn enumerate_formats(&self) -> Result<Vec<CameraFormat>, NokhwaError>;
2110

@@ -35,53 +24,42 @@ pub trait Setting {
3524
) -> Result<(), NokhwaError>;
3625
}
3726

38-
// #[cfg(feature = "async")]
39-
// pub trait AsyncSetting {
40-
// async fn set_format_async(&self, camera_format: CameraFormat) -> Result<(), NokhwaError>;
41-
//
42-
// async fn set_property_async(
43-
// &mut self,
44-
// property: &CameraPropertyId,
45-
// value: CameraPropertyValue,
46-
// ) -> Result<(), NokhwaError>;
47-
//
48-
// def_camera_props_async!(
49-
// Brightness,
50-
// Contrast,
51-
// Hue,
52-
// Saturation,
53-
// Sharpness,
54-
// Gamma,
55-
// WhiteBalance,
56-
// BacklightCompensation,
57-
// Pan,
58-
// Tilt,
59-
// Zoom,
60-
// Exposure,
61-
// Iris,
62-
// Focus,
63-
// Facing,
64-
// );
65-
// }
27+
#[cfg(feature = "async")]
28+
pub trait AsyncSetting {
29+
async fn enumerate_formats_async(&self) -> Result<Vec<CameraFormat>, NokhwaError>;
30+
31+
async fn enumerate_resolution_and_frame_rates_async(
32+
&self,
33+
frame_format: FrameFormat,
34+
) -> Result<HashMap<Resolution, Vec<FrameRate>>, NokhwaError>;
35+
36+
async fn set_format_async(&self, camera_format: CameraFormat) -> Result<(), NokhwaError>;
37+
38+
async fn properties_async(&self) -> &Properties;
39+
40+
async fn set_property_async(
41+
&mut self,
42+
property: &ControlId,
43+
value: ControlValue,
44+
) -> Result<(), NokhwaError>;
45+
}
6646

6747
pub trait Capture {
48+
// Implementations MUST guarantee that there can only ever be one stream open at once.
6849
fn open_stream(&mut self) -> Result<Stream, NokhwaError>;
6950

51+
// Implementations MUST be multi-close tolerant.
7052
fn close_stream(&mut self) -> Result<(), NokhwaError>;
7153
}
7254

7355
#[cfg(feature = "async")]
7456
pub trait AsyncStream {
75-
async fn open_stream(&mut self) -> Result<(), NokhwaError>;
57+
async fn open_stream_async(&mut self) -> Result<Stream, NokhwaError>;
7658

77-
async fn await_frame(&mut self) -> Result<FrameBuffer, NokhwaError>;
78-
79-
async fn close_stream(&mut self) -> Result<(), NokhwaError>;
59+
async fn close_stream_async(&mut self) -> Result<(), NokhwaError>;
8060
}
8161

82-
pub trait CameraVtable: Setting + Capture {}
83-
84-
pub trait Camera: Open + CameraVtable {}
62+
pub trait Camera: Setting + Capture {}
8563

8664
#[cfg(feature = "async")]
87-
pub trait AsyncCapture: Camera + AsyncOpen + AsyncStream {}
65+
pub trait AsyncCamera: Camera + AsyncSetting + AsyncStream {}

nokhwa-core/src/error.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use crate::{frame_format::FrameFormat, types::ApiBackend};
1717
use std::fmt::{Debug};
1818
use thiserror::Error;
19+
use crate::platform::Backends;
1920

2021
pub type NokhwaResult<T> = Result<T, NokhwaError>;
2122

@@ -56,9 +57,11 @@ pub enum NokhwaError {
5657
#[error("Could not stop stream: {0}")]
5758
StreamShutdownError(String),
5859
#[error("This operation is not supported by backend {0}.")]
59-
UnsupportedOperationError(ApiBackend),
60+
UnsupportedOperationError(Backends),
6061
#[error("This operation is not implemented yet: {0}")]
6162
NotImplementedError(String),
6263
#[error("Failed To Convert: {0}")]
6364
ConversionError(String),
65+
#[error("Permission denied by user.")]
66+
PermissionDenied,
6467
}

nokhwa-core/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,4 @@ pub mod traits;
3535
pub mod types;
3636
pub mod utils;
3737
pub mod stream;
38+
mod platform;

nokhwa-core/src/platform.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
use crate::camera::{AsyncCamera, Camera};
2+
use crate::error::NokhwaResult;
3+
use crate::types::{CameraIndex, CameraInformation};
4+
5+
#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq)]
6+
pub enum Backends {
7+
Video4Linux2,
8+
WebWASM,
9+
AVFoundation,
10+
MicrosoftMediaFoundation,
11+
Custom(&'static str)
12+
}
13+
14+
pub trait PlatformTrait {
15+
const PLATFORM: Backends;
16+
type Camera: Camera;
17+
18+
19+
fn block_on_permission(&mut self) -> NokhwaResult<()>;
20+
21+
fn check_permission_given(&mut self) -> bool;
22+
23+
fn query(&mut self) -> NokhwaResult<Vec<CameraInformation>>;
24+
25+
fn open(&mut self, index: &CameraIndex) -> NokhwaResult<Self::Camera>;
26+
}
27+
28+
#[cfg(feature = "async")]
29+
pub trait AsyncPlatformTrait {
30+
const PLATFORM: Backends;
31+
type AsyncCamera: AsyncCamera;
32+
33+
34+
async fn await_permission(&mut self) -> NokhwaResult<()>;
35+
36+
async fn query_async(&mut self) -> NokhwaResult<Vec<CameraInformation>>;
37+
38+
async fn open_async (&mut self, index: &CameraIndex) -> NokhwaResult<Self::AsyncCamera>;
39+
}

nokhwa-core/src/query.rs

Lines changed: 0 additions & 10 deletions
This file was deleted.

nokhwa-core/src/stream.rs

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::error::{NokhwaError, NokhwaResult};
22
use crate::frame_buffer::FrameBuffer;
3-
use flume::Receiver;
3+
use flume::{Receiver, TryRecvError};
44
use std::sync::Arc;
55

66
pub trait StreamInnerTrait {
@@ -26,47 +26,54 @@ impl Stream {
2626
// }
2727
// }
2828

29-
pub fn poll_frame(&self) -> NokhwaResult<FrameBuffer> {
29+
pub fn check_disconnected(&self) -> NokhwaResult<()> {
3030
if self.inner.receiver().is_disconnected() {
3131
return Err(NokhwaError::ReadFrameError(
3232
"stream is disconnected!".to_string(),
33-
));
33+
))
3434
}
35+
Ok(())
36+
}
37+
38+
pub fn poll_frame(&self) -> NokhwaResult<FrameBuffer> {
39+
self.check_disconnected()?;
3540

3641
self.inner
3742
.receiver()
3843
.recv()
3944
.map_err(|why| NokhwaError::ReadFrameError(why.to_string()))
4045
}
4146

42-
pub fn try_poll_frame(&self) -> Option<NokhwaResult<FrameBuffer>> {
43-
if self.inner.receiver().is_disconnected() {
44-
return Some(Err(NokhwaError::ReadFrameError(
45-
"stream is disconnected!".to_string(),
46-
)));
47-
}
47+
pub fn try_poll_frame(&self) -> NokhwaResult<Option<FrameBuffer>> {
48+
self.check_disconnected()?;
4849

4950
if self.inner.receiver().is_empty() {
50-
return None;
51+
return Ok(None);
52+
}
53+
54+
let possible_frame = self.inner
55+
.receiver()
56+
.try_recv();
57+
58+
match possible_frame {
59+
Ok(f) => Ok(Some(f)),
60+
Err(why) => {
61+
match why {
62+
TryRecvError::Empty => Ok(None),
63+
TryRecvError::Disconnected => Err(NokhwaError::ReadFrameError(
64+
"stream is disconnected!".to_string(),
65+
))
66+
}
67+
}
5168
}
5269

53-
Some(
54-
self.inner
55-
.receiver()
56-
.try_recv()
57-
.map_err(|why| NokhwaError::ReadFrameError(why.to_string())),
58-
)
5970
}
6071

6172
#[cfg(feature = "async")]
6273
pub async fn await_frame(&self) -> NokhwaResult<FrameBuffer> {
6374
use futures::TryFutureExt;
6475

65-
if self.inner.receiver().is_disconnected() {
66-
return Err(NokhwaError::ReadFrameError(
67-
"stream is disconnected!".to_string(),
68-
));
69-
}
76+
self.check_disconnected()?;
7077

7178
self.inner
7279
.receiver()

0 commit comments

Comments
 (0)