mirror of
https://github.com/l1npengtul/nokhwa.git
synced 2026-07-04 02:27:26 +00:00
make control api simpler, because most platforms arnt v4l2
This commit is contained in:
Generated
+2
-20
@@ -1,6 +1,6 @@
|
|||||||
# This file is automatically @generated by Cargo.
|
# This file is automatically @generated by Cargo.
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 4
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ab_glyph"
|
name = "ab_glyph"
|
||||||
@@ -2516,6 +2516,7 @@ dependencies = [
|
|||||||
"futures",
|
"futures",
|
||||||
"image 0.25.0",
|
"image 0.25.0",
|
||||||
"num-rational 0.4.2",
|
"num-rational 0.4.2",
|
||||||
|
"num-traits",
|
||||||
"opencv 0.93.1",
|
"opencv 0.93.1",
|
||||||
"paste",
|
"paste",
|
||||||
"rgb",
|
"rgb",
|
||||||
@@ -2524,16 +2525,6 @@ dependencies = [
|
|||||||
"wgpu 23.0.1",
|
"wgpu 23.0.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "nokhwa-decoder"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"dcv-color-primitives",
|
|
||||||
"mozjpeg",
|
|
||||||
"nokhwa-core",
|
|
||||||
"yuvutils-rs",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nokhwactl"
|
name = "nokhwactl"
|
||||||
version = "0.10.0"
|
version = "0.10.0"
|
||||||
@@ -4745,15 +4736,6 @@ version = "0.8.19"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0fcb9cbac069e033553e8bb871be2fbdffcab578eb25bd0f7c508cedc6dcd75a"
|
checksum = "0fcb9cbac069e033553e8bb871be2fbdffcab578eb25bd0f7c508cedc6dcd75a"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "yuvutils-rs"
|
|
||||||
version = "0.5.8"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b30a62ce6c5fbf13dbf8d92e7cd805d74574a7f84d0e81462ca3cb8192be5de2"
|
|
||||||
dependencies = [
|
|
||||||
"num-traits",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerocopy"
|
name = "zerocopy"
|
||||||
version = "0.7.32"
|
version = "0.7.32"
|
||||||
|
|||||||
+1
-1
@@ -12,7 +12,7 @@ repository = "https://github.com/l1npengtul/nokhwa"
|
|||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
members = ["nokhwa-bindings-macos", "nokhwa-bindings-windows", "nokhwa-bindings-linux", "nokhwa-core", "examples/*", "nokhwa-decoder"]
|
members = ["nokhwa-bindings-macos", "nokhwa-bindings-windows", "nokhwa-bindings-linux", "nokhwa-core", "examples/*"]
|
||||||
exclude = ["examples/jscam"]
|
exclude = ["examples/jscam"]
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
|
|||||||
Generated
+9
-9
@@ -5,11 +5,11 @@
|
|||||||
"systems": "systems"
|
"systems": "systems"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1726560853,
|
"lastModified": 1731533236,
|
||||||
"narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=",
|
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
||||||
"owner": "numtide",
|
"owner": "numtide",
|
||||||
"repo": "flake-utils",
|
"repo": "flake-utils",
|
||||||
"rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a",
|
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -20,11 +20,11 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1730958623,
|
"lastModified": 1733097829,
|
||||||
"narHash": "sha256-JwQZIGSYnRNOgDDoIgqKITrPVil+RMWHsZH1eE1VGN0=",
|
"narHash": "sha256-9hbb1rqGelllb4kVUCZ307G2k3/UhmA8PPGBoyuWaSw=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "85f7e662eda4fa3a995556527c87b2524b691933",
|
"rev": "2c15aa59df0017ca140d9ba302412298ab4bf22a",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -62,11 +62,11 @@
|
|||||||
"nixpkgs": "nixpkgs_2"
|
"nixpkgs": "nixpkgs_2"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1731292155,
|
"lastModified": 1733193245,
|
||||||
"narHash": "sha256-fYVoUUtSadbOrH0z0epVQDsStBDS/S/fAK//0ECQAAI=",
|
"narHash": "sha256-nwvKoPi3S6XyliqBRuC+01QFF0k94ZOvnoZtbGi/ObM=",
|
||||||
"owner": "oxalica",
|
"owner": "oxalica",
|
||||||
"repo": "rust-overlay",
|
"repo": "rust-overlay",
|
||||||
"rev": "7c4cd99ed7604b79e8cb721099ac99c66f656b3a",
|
"rev": "3458f7f946ba61d1a1069aedcc17d7b7616f23cd",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|||||||
@@ -246,7 +246,7 @@ mod internal {
|
|||||||
ffi::{c_float, c_void, CStr},
|
ffi::{c_float, c_void, CStr},
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
};
|
};
|
||||||
use nokhwa_core::properties::{CameraControl, ControlValueDescription, ControlValueSetter, KnownCameraControl};
|
use nokhwa_core::properties::{CameraControl, ControlValueDescription, ControlValue, KnownCameraControl};
|
||||||
|
|
||||||
const UTF8_ENCODING: usize = 4;
|
const UTF8_ENCODING: usize = 4;
|
||||||
type CGFloat = c_float;
|
type CGFloat = c_float;
|
||||||
@@ -1492,7 +1492,7 @@ mod internal {
|
|||||||
pub fn set_control(
|
pub fn set_control(
|
||||||
&mut self,
|
&mut self,
|
||||||
id: KnownCameraControl,
|
id: KnownCameraControl,
|
||||||
value: ControlValueSetter,
|
value: ControlValue,
|
||||||
) -> Result<(), NokhwaError> {
|
) -> Result<(), NokhwaError> {
|
||||||
let rc = self.get_controls()?;
|
let rc = self.get_controls()?;
|
||||||
let controls = rc
|
let controls = rc
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ pub mod wmf {
|
|||||||
Arc,
|
Arc,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use nokhwa_core::properties::{CameraControl, ControlValueDescription, ControlValueSetter, KnownCameraControl};
|
use nokhwa_core::properties::{CameraControl, ControlValueDescription, ControlValue, KnownCameraControl};
|
||||||
use windows::Win32::Media::DirectShow::{CameraControl_Flags_Auto, CameraControl_Flags_Manual};
|
use windows::Win32::Media::DirectShow::{CameraControl_Flags_Auto, CameraControl_Flags_Manual};
|
||||||
use windows::Win32::Media::MediaFoundation::{
|
use windows::Win32::Media::MediaFoundation::{
|
||||||
IMFMediaType, MFCreateSample, MF_SOURCE_READER_FIRST_VIDEO_STREAM,
|
IMFMediaType, MFCreateSample, MF_SOURCE_READER_FIRST_VIDEO_STREAM,
|
||||||
@@ -849,7 +849,7 @@ pub mod wmf {
|
|||||||
pub fn set_control(
|
pub fn set_control(
|
||||||
&mut self,
|
&mut self,
|
||||||
control: KnownCameraControl,
|
control: KnownCameraControl,
|
||||||
value: ControlValueSetter,
|
value: ControlValue,
|
||||||
) -> Result<(), NokhwaError> {
|
) -> Result<(), NokhwaError> {
|
||||||
let current_value = self.control(control)?;
|
let current_value = self.control(control)?;
|
||||||
|
|
||||||
@@ -897,8 +897,8 @@ pub mod wmf {
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
let ctrl_value = match value {
|
let ctrl_value = match value {
|
||||||
ControlValueSetter::Integer(i) => i as i32,
|
ControlValue::Integer(i) => i as i32,
|
||||||
ControlValueSetter::Boolean(b) => i32::from(b),
|
ControlValue::Boolean(b) => i32::from(b),
|
||||||
v => {
|
v => {
|
||||||
return Err(NokhwaError::StructureError {
|
return Err(NokhwaError::StructureError {
|
||||||
structure: format!("ControlValueSetter {}", v),
|
structure: format!("ControlValueSetter {}", v),
|
||||||
@@ -1229,7 +1229,7 @@ pub mod wmf {
|
|||||||
CameraFormat, CameraIndex, CameraInfo,
|
CameraFormat, CameraIndex, CameraInfo,
|
||||||
};
|
};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use nokhwa_core::properties::{CameraControl, ControlValueSetter, KnownCameraControl};
|
use nokhwa_core::properties::{CameraControl, ControlValue, KnownCameraControl};
|
||||||
|
|
||||||
pub fn initialize_mf() -> Result<(), NokhwaError> {
|
pub fn initialize_mf() -> Result<(), NokhwaError> {
|
||||||
Err(NokhwaError::NotImplementedError(
|
Err(NokhwaError::NotImplementedError(
|
||||||
@@ -1287,7 +1287,7 @@ pub mod wmf {
|
|||||||
pub fn set_control(
|
pub fn set_control(
|
||||||
&mut self,
|
&mut self,
|
||||||
_control: KnownCameraControl,
|
_control: KnownCameraControl,
|
||||||
_value: ControlValueSetter,
|
_value: ControlValue,
|
||||||
) -> Result<(), NokhwaError> {
|
) -> Result<(), NokhwaError> {
|
||||||
Err(NokhwaError::NotImplementedError(
|
Err(NokhwaError::NotImplementedError(
|
||||||
"Only on Windows".to_string(),
|
"Only on Windows".to_string(),
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ thiserror = "2.0"
|
|||||||
bytes = "1.3"
|
bytes = "1.3"
|
||||||
paste = "1.0"
|
paste = "1.0"
|
||||||
flume = "0.11"
|
flume = "0.11"
|
||||||
|
num-traits = "0.2"
|
||||||
|
|
||||||
[dependencies.num-rational]
|
[dependencies.num-rational]
|
||||||
version = "0.4"
|
version = "0.4"
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
use crate::error::{NokhwaError, NokhwaResult};
|
use crate::error::{NokhwaError, NokhwaResult};
|
||||||
use crate::frame_buffer::FrameBuffer;
|
|
||||||
use crate::frame_format::FrameFormat;
|
use crate::frame_format::FrameFormat;
|
||||||
use crate::properties::{CameraProperties, CameraPropertyId, CameraPropertyValue};
|
use crate::properties::{CameraProperties, CameraPropertyId, CameraPropertyValue};
|
||||||
use crate::types::{CameraFormat, CameraIndex, FrameRate, Resolution};
|
use crate::types::{CameraFormat, CameraIndex, FrameRate, Resolution};
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
use crate::{error::NokhwaError, frame_buffer::FrameBuffer, frame_format::FrameFormat};
|
use crate::{error::NokhwaError, frame_buffer::FrameBuffer, frame_format::FrameFormat};
|
||||||
use image::{ImageBuffer, Pixel};
|
use image::{ImageBuffer, Pixel};
|
||||||
use std::{
|
use std::{
|
||||||
error::Error,
|
|
||||||
fmt::{Debug, Display},
|
|
||||||
ops::{ControlFlow, Deref},
|
ops::{ControlFlow, Deref},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ use crate::{
|
|||||||
types::{CameraFormat, FrameRate, Resolution},
|
types::{CameraFormat, FrameRate, Resolution},
|
||||||
};
|
};
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
|
use crate::ranges::ValidatableRange;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialOrd, PartialEq)]
|
#[derive(Copy, Clone, Debug, PartialOrd, PartialEq)]
|
||||||
enum ClosestType {
|
enum ClosestType {
|
||||||
@@ -60,24 +61,29 @@ impl FormatRequest {
|
|||||||
frame_rate,
|
frame_rate,
|
||||||
frame_format,
|
frame_format,
|
||||||
} => {
|
} => {
|
||||||
let resolution_point = resolution.map(|x| x.preferred())?;
|
let resolution_point = resolution.map(|x| x.preferred());
|
||||||
|
let frame_rate_point = frame_rate.map(|x| x.preferred());
|
||||||
let frame_rate_point = frame_rate.map(|x| x.preferred())?;
|
|
||||||
// lets calcuate distance in 3 dimensions (add both resolution and frame_rate together)
|
// lets calcuate distance in 3 dimensions (add both resolution and frame_rate together)
|
||||||
|
|
||||||
let mut distances: Vec<(f32, CameraFormat)> = list_of_formats
|
let mut distances = list_of_formats
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|x| frame_format.contains(&x.format()))
|
.filter(|x| frame_format.contains(&x.format()))
|
||||||
.map(|fmt| {
|
.map(|fmt| {
|
||||||
(
|
let frame_rate_distance = match frame_rate_point {
|
||||||
(fmt.frame_rate() - frame_rate_point).abs()
|
Some(f_point) => (fmt.frame_rate() - f_point).approximate_float().unwrap_or(f32::INFINITY).abs(),
|
||||||
+ fmt.resolution().distance_from(&resolution_point) as f32,
|
None => 0_f32,
|
||||||
fmt,
|
};
|
||||||
)
|
|
||||||
|
let resolution_point_distance = match resolution_point {
|
||||||
|
Some(res_pt) => fmt.resolution().distance_from(&res_pt) as f32,
|
||||||
|
None => 0_f32,
|
||||||
|
};
|
||||||
|
|
||||||
|
(frame_rate_distance + resolution_point_distance, fmt)
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<(f32, &CameraFormat)>>();
|
||||||
distances.sort_by(|a, b| a.0.partial_cmp(&b.0).unwrap_or(Ordering::Equal));
|
distances.sort_by(|a, b| a.0.partial_cmp(&b.0).unwrap_or(Ordering::Equal));
|
||||||
distances.into_iter().map(|x| x.1).collect()
|
distances.into_iter().map(|x| x.1).copied().collect()
|
||||||
}
|
}
|
||||||
FormatRequest::HighestFrameRate {
|
FormatRequest::HighestFrameRate {
|
||||||
frame_rate,
|
frame_rate,
|
||||||
@@ -86,7 +92,7 @@ impl FormatRequest {
|
|||||||
let mut formats = list_of_formats
|
let mut formats = list_of_formats
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|x| {
|
.filter(|x| {
|
||||||
frame_format.contains(&x.format()) && frame_rate.in_range(x.frame_rate())
|
frame_format.contains(&x.format()) && frame_rate.validate(&x.frame_rate()).is_ok()
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
formats.sort();
|
formats.sort();
|
||||||
@@ -99,7 +105,7 @@ impl FormatRequest {
|
|||||||
let mut formats = list_of_formats
|
let mut formats = list_of_formats
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|x| {
|
.filter(|x| {
|
||||||
frame_format.contains(&x.format()) && resolution.in_range(x.resolution())
|
frame_format.contains(&x.format()) && resolution.validate(&x.resolution()).is_ok()
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
formats.sort();
|
formats.sort();
|
||||||
|
|||||||
+75
-646
@@ -1,676 +1,105 @@
|
|||||||
use crate::error::NokhwaError;
|
use std::collections::HashMap;
|
||||||
use crate::ranges::{ArrayRange, KeyValue, Options, Range, RangeValidationFailure, Simple, ValidatableRange};
|
use crate::ranges::Range;
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use std::cmp::Ordering;
|
|
||||||
use std::{
|
|
||||||
collections::{HashMap, HashSet},
|
|
||||||
fmt::{Display, Formatter},
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Hash, Ord, PartialOrd, Eq, PartialEq)]
|
#[derive(Copy, Clone, Debug, Hash, Ord, PartialOrd, Eq, PartialEq)]
|
||||||
pub struct ControlValidationFailure;
|
pub enum ControlId {
|
||||||
|
|
||||||
impl From<RangeValidationFailure> for ControlValidationFailure {
|
|
||||||
fn from(_: RangeValidationFailure) -> Self {
|
|
||||||
Self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Hash, Ord, PartialOrd, Eq, PartialEq)]
|
|
||||||
pub enum CameraPropertyId {
|
|
||||||
Brightness,
|
|
||||||
Contrast,
|
|
||||||
Hue,
|
|
||||||
Saturation,
|
|
||||||
Sharpness,
|
|
||||||
Gamma,
|
|
||||||
WhiteBalance,
|
|
||||||
BacklightCompensation,
|
|
||||||
ISO,
|
|
||||||
Pan,
|
|
||||||
Tilt,
|
|
||||||
Zoom,
|
|
||||||
Exposure,
|
|
||||||
Iris,
|
|
||||||
Focus,
|
Focus,
|
||||||
Facing,
|
|
||||||
Custom(String),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for CameraPropertyId {
|
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
||||||
write!(f, "{self:?}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Replace Controls API with Properties. (this one)
|
|
||||||
/// Properties of a Camera.
|
|
||||||
///
|
|
||||||
/// If the property is not supported, it is `None`.
|
|
||||||
/// Custom or platform-specific properties go into `other`
|
|
||||||
pub struct CameraProperties {
|
|
||||||
props: HashMap<CameraPropertyId, CameraPropertyDescriptor>,
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! def_camera_props {
|
|
||||||
( $($property:ident, )* ) => {
|
|
||||||
paste::paste! {
|
|
||||||
impl CameraProperties {
|
|
||||||
$(
|
|
||||||
pub fn [<$property:snake>] (&self) -> Option<&CameraPropertyDescriptor> {
|
|
||||||
self.props.get(&CameraPropertyId::$property)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn [<set_ $property:snake>] (&mut self, value: CameraPropertyValue) -> Result<(), NokhwaError> {
|
|
||||||
self.set_property(&CameraPropertyId::$property, value)
|
|
||||||
}
|
|
||||||
)*
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
def_camera_props!(
|
|
||||||
Brightness,
|
|
||||||
Contrast,
|
|
||||||
Hue,
|
|
||||||
Saturation,
|
|
||||||
Sharpness,
|
|
||||||
Gamma,
|
|
||||||
WhiteBalance,
|
|
||||||
BacklightCompensation,
|
|
||||||
ISO,
|
|
||||||
Pan,
|
|
||||||
Tilt,
|
|
||||||
Zoom,
|
|
||||||
Exposure,
|
Exposure,
|
||||||
Iris,
|
WhiteBalance,
|
||||||
Focus,
|
Zoom,
|
||||||
Facing,
|
Lighting,
|
||||||
);
|
Other(u64)
|
||||||
|
|
||||||
impl CameraProperties {
|
|
||||||
pub fn property(&self, property: &CameraPropertyId) -> Option<&CameraPropertyDescriptor> {
|
|
||||||
self.props.get(property)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_property(
|
|
||||||
&mut self,
|
|
||||||
property: &CameraPropertyId,
|
|
||||||
value: CameraPropertyValue,
|
|
||||||
) -> Result<(), NokhwaError> {
|
|
||||||
match self.props.get_mut(property) {
|
|
||||||
Some(prop) => {
|
|
||||||
prop.set_value(value)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
None => Err(NokhwaError::SetPropertyError {
|
|
||||||
property: property.to_string(),
|
|
||||||
value: value.to_string(),
|
|
||||||
error: String::from("Is null."),
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Describes an individual property.
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
#[derive(Clone, Debug)]
|
pub enum ControlGroup {
|
||||||
pub struct CameraPropertyDescriptor {
|
ModeMultipleValue(ModeAndValuesControl),
|
||||||
flags: HashSet<CameraPropertyFlag>,
|
Simple(SimpleControl),
|
||||||
mode: CameraPropertyMode,
|
|
||||||
range: CameraPropertyRange,
|
|
||||||
value: CameraPropertyValue,
|
|
||||||
value_type: CameraPropertyValueType,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CameraPropertyDescriptor {
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub fn new(
|
pub struct ModeAndValuesControl {
|
||||||
flags: &[CameraPropertyFlag],
|
id: ControlId,
|
||||||
mode: CameraPropertyMode,
|
mode_id: u64,
|
||||||
range: CameraPropertyRange,
|
mode_body: ControlBody,
|
||||||
value: CameraPropertyValue,
|
values: HashMap<String, SimpleControl>
|
||||||
value_type: CameraPropertyValueType,
|
|
||||||
) -> Result<Self, NokhwaError> {
|
|
||||||
if flags.contains(&CameraPropertyFlag::ReadOnly)
|
|
||||||
&& flags.contains(&CameraPropertyFlag::WriteOnly)
|
|
||||||
{
|
|
||||||
return Err(NokhwaError::StructureError {
|
|
||||||
structure: "CameraPropertyDescriptor".to_string(),
|
|
||||||
error: "conflicting flags".to_string(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(CameraPropertyDescriptor {
|
|
||||||
flags: HashSet::from(flags),
|
|
||||||
mode,
|
|
||||||
range,
|
|
||||||
value,
|
|
||||||
value_type,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_read_only(&self) -> bool {
|
|
||||||
self.flags.contains(&CameraPropertyFlag::ReadOnly)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_write_only(&self) -> bool {
|
|
||||||
self.flags.contains(&CameraPropertyFlag::WriteOnly)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_disabled(&self) -> Result<(), NokhwaError> {
|
|
||||||
if self.flags.contains(&CameraPropertyFlag::Disabled) {
|
|
||||||
return Err(NokhwaError::StructureError {
|
|
||||||
structure: "CameraPropertyDescriptor".to_string(),
|
|
||||||
error: "Disabled".to_string(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn flags(&self) -> Result<&HashSet<CameraPropertyFlag>, NokhwaError> {
|
|
||||||
self.is_disabled()?;
|
|
||||||
Ok(&self.flags)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn mode(&self) -> CameraPropertyMode {
|
|
||||||
self.mode
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn value_type(&self) -> CameraPropertyValueType {
|
|
||||||
self.value_type
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn range(&self) -> &CameraPropertyRange {
|
|
||||||
&self.range
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn value(&self) -> &CameraPropertyValue {
|
|
||||||
&self.value
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_value(&mut self, value: CameraPropertyValue) -> Result<(), NokhwaError> {
|
|
||||||
self.range
|
|
||||||
.check_value(&value)
|
|
||||||
.map_err(|_| NokhwaError::SetPropertyError {
|
|
||||||
property: "CameraPropertyValue".to_string(),
|
|
||||||
value: value.to_string(),
|
|
||||||
error: "Bad Type".to_string(),
|
|
||||||
})?;
|
|
||||||
self.value = value;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Platform Specific Camera Property. This is not useful, unless you are manually dealing with
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
/// camera properties in `other`.
|
pub struct SimpleControl {
|
||||||
#[derive(Clone, Debug, Hash, PartialOrd, Eq, PartialEq)]
|
id: u64,
|
||||||
#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
|
body: ControlBody,
|
||||||
pub enum CameraCustomPropertyPlatformId {
|
}
|
||||||
String(String),
|
|
||||||
LongInteger(i128),
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
pub struct ControlBody {
|
||||||
|
pub typ: ControlType,
|
||||||
|
pub class: ControlClass,
|
||||||
|
pub flags: Vec<ControlFlags>,
|
||||||
|
pub descriptor: ControlValueDescriptor,
|
||||||
|
pub value: Option<ControlValue>
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Hash, Ord, PartialOrd, Eq, PartialEq)]
|
#[derive(Copy, Clone, Debug, Hash, Ord, PartialOrd, Eq, PartialEq)]
|
||||||
#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
|
pub enum ControlType {
|
||||||
pub enum CameraPropertyMode {
|
Button,
|
||||||
///
|
Integer,
|
||||||
None,
|
Menu,
|
||||||
/// Automatically Set
|
IntegerMenu,
|
||||||
Automatic,
|
BinaryMenu,
|
||||||
/// Manually Set
|
Bitmask,
|
||||||
Manual,
|
String,
|
||||||
/// Continuously Set
|
|
||||||
Continuous,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Hash, Ord, PartialOrd, Eq, PartialEq)]
|
#[derive(Copy, Clone, Debug, Hash, Ord, PartialOrd, Eq, PartialEq)]
|
||||||
#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
|
pub enum ControlClass {
|
||||||
pub enum CameraPropertyValueType {
|
User,
|
||||||
/// Relative
|
Camera,
|
||||||
Relative,
|
Other(u64),
|
||||||
/// Absolute
|
|
||||||
Absolute,
|
|
||||||
/// Unknown/Unused/Not Applicable
|
|
||||||
None,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The flags that a camera property may have.
|
|
||||||
#[derive(Copy, Clone, Debug, Hash, Ord, PartialOrd, Eq, PartialEq)]
|
#[derive(Copy, Clone, Debug, Hash, Ord, PartialOrd, Eq, PartialEq)]
|
||||||
#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
|
pub enum ControlFlags {
|
||||||
pub enum CameraPropertyFlag {
|
|
||||||
/// The value may only be read from - any attempts to change the value will error.
|
|
||||||
ReadOnly,
|
|
||||||
/// The value can only be written to.
|
|
||||||
WriteOnly,
|
|
||||||
/// May just randomly poof out of existance.
|
|
||||||
// FIXME: where the fuck did i find this? replace above doc with actual info.
|
|
||||||
Volatile,
|
|
||||||
/// While the platform/driver supports this feature,
|
|
||||||
/// your camera does not. Setting will be ignored.
|
|
||||||
Disabled,
|
Disabled,
|
||||||
|
Busy,
|
||||||
|
ReadOnly,
|
||||||
|
CascadingUpdates,
|
||||||
|
Inactive,
|
||||||
|
Slider,
|
||||||
|
WriteOnly,
|
||||||
|
ContinuousChange,
|
||||||
|
ExecuteOnWrite,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for CameraPropertyFlag {
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
pub enum ControlValueDescriptor {
|
||||||
write!(f, "{self:?}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Ranges (Available Options of a Camera
|
|
||||||
#[non_exhaustive]
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub enum CameraPropertyRange {
|
|
||||||
Null,
|
Null,
|
||||||
Boolean(Simple<bool>),
|
|
||||||
Integer(Range<i64>),
|
Integer(Range<i64>),
|
||||||
LongInteger(Range<i128>),
|
Bitmap(i64),
|
||||||
Float(Range<f32>),
|
Float(Range<i64>),
|
||||||
Double(Range<f64>),
|
|
||||||
String(Simple<String>),
|
|
||||||
Array(ArrayRange<Vec<CameraPropertyValue>>),
|
|
||||||
Enumeration(Options<CameraPropertyValue>),
|
|
||||||
Binary(Simple<Vec<u8>>),
|
|
||||||
Pair(Range<f32>, Range<f32>),
|
|
||||||
Triple(
|
|
||||||
Range<f32>,
|
|
||||||
Range<f32>,
|
|
||||||
Range<f32>,
|
|
||||||
),
|
|
||||||
Quadruple(
|
|
||||||
Range<f32>,
|
|
||||||
Range<f32>,
|
|
||||||
Range<f32>,
|
|
||||||
Range<f32>,
|
|
||||||
),
|
|
||||||
KeyValuePair(KeyValue<String, CameraPropertyValue>),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CameraPropertyRange {
|
|
||||||
pub fn check_value(&self, value: &CameraPropertyValue) -> Result<(), ControlValidationFailure> {
|
|
||||||
match self {
|
|
||||||
CameraPropertyRange::Null => {
|
|
||||||
if let CameraPropertyValue::Null = value {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CameraPropertyRange::Boolean(chk_b) => {
|
|
||||||
if let CameraPropertyValue::Boolean(b) = value {
|
|
||||||
chk_b.validate(b)?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CameraPropertyRange::Integer(chk_i) => {
|
|
||||||
if let CameraPropertyValue::Integer(i) = value {
|
|
||||||
chk_i.validate(i)?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CameraPropertyRange::LongInteger(chk_long) => {
|
|
||||||
if let CameraPropertyValue::LongInteger(long) = value {
|
|
||||||
chk_long.validate(long)?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CameraPropertyRange::Float(chk_float) => {
|
|
||||||
if let CameraPropertyValue::Float(fl) = value {
|
|
||||||
chk_float.validate(fl)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CameraPropertyRange::Double(chk_double) => {
|
|
||||||
if let CameraPropertyValue::Double(dl) = value {
|
|
||||||
chk_double.validate(dl)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CameraPropertyRange::String(chk_string) => {
|
|
||||||
if let CameraPropertyValue::String(st) = value {
|
|
||||||
chk_string.validate(st)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CameraPropertyRange::Array(chk_array) => {
|
|
||||||
if let CameraPropertyValue::Array(arr) = value {
|
|
||||||
chk_array.validate(arr)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CameraPropertyRange::Enumeration(chk_enum) => {
|
|
||||||
if let CameraPropertyValue::EnumValue(en) = value {
|
|
||||||
chk_enum.validate(en)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CameraPropertyRange::Binary(chk_bin) => {
|
|
||||||
if let CameraPropertyValue::Binary(bin) = value {
|
|
||||||
chk_bin.validate(bin)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CameraPropertyRange::Pair(chk_a, chk_b) => {
|
|
||||||
if let CameraPropertyValue::Pair(a, b) = value {
|
|
||||||
chk_a.validate(a)?;
|
|
||||||
chk_b.validate(b)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CameraPropertyRange::Triple(chk_x, chk_y, chk_z) => {
|
|
||||||
if let CameraPropertyValue::Triple(x, y, z) = value {
|
|
||||||
chk_x.validate(x)?;
|
|
||||||
chk_y.validate(y)?;
|
|
||||||
chk_z.validate(z)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CameraPropertyRange::Quadruple(chk_x, chk_y, chk_z, chk_w) => {
|
|
||||||
if let CameraPropertyValue::Quadruple(x, y, z, w) = value {
|
|
||||||
chk_x.validate(x)?;
|
|
||||||
chk_y.validate(y)?;
|
|
||||||
chk_z.validate(z)?;
|
|
||||||
chk_w.validate(w)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CameraPropertyRange::KeyValuePair(kv) => {
|
|
||||||
if let CameraPropertyValue::KeyValue(st, va) = value {
|
|
||||||
if let Some(vk) = kv.by_key(st) {
|
|
||||||
if vk.is_same_type(va) {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => return Err(ControlValidationFailure),
|
|
||||||
}
|
|
||||||
Err(ControlValidationFailure)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A possible value of
|
|
||||||
///
|
|
||||||
/// IMPORTANT: Make sure to call [`check_self()`] BEFORE any other operations!
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
#[non_exhaustive]
|
|
||||||
pub enum CameraPropertyValue {
|
|
||||||
Null,
|
|
||||||
Boolean(bool),
|
|
||||||
Integer(i64),
|
|
||||||
LongInteger(i128),
|
|
||||||
Float(f32),
|
|
||||||
Double(f64),
|
|
||||||
String(String),
|
String(String),
|
||||||
Array(Vec<CameraPropertyValue>),
|
Boolean(bool),
|
||||||
EnumValue(Box<CameraPropertyValue>),
|
Array(Vec<ControlValuePrimitive>),
|
||||||
Binary(Vec<u8>),
|
Map(HashMap<String, ControlValuePrimitive>)
|
||||||
Pair(f32, f32),
|
|
||||||
Triple(f32, f32, f32),
|
|
||||||
Quadruple(f32, f32, f32, f32),
|
|
||||||
KeyValue(String, Box<CameraPropertyValue>),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CameraPropertyValue {
|
#[derive(Clone, Debug, PartialEq, PartialOrd)]
|
||||||
pub fn is_same_type(&self, other: &CameraPropertyValue) -> bool {
|
pub enum ControlValuePrimitive {
|
||||||
match (self, other) {
|
Null,
|
||||||
(CameraPropertyValue::Null, CameraPropertyValue::Null) => true,
|
Integer(i64),
|
||||||
(CameraPropertyValue::Boolean(_), CameraPropertyValue::Boolean(_)) => true,
|
Bitmap(i64),
|
||||||
(CameraPropertyValue::Integer(_), CameraPropertyValue::Integer(_)) => true,
|
Float(f64),
|
||||||
(CameraPropertyValue::LongInteger(_), CameraPropertyValue::LongInteger(_)) => true,
|
String(String),
|
||||||
(CameraPropertyValue::Float(_), CameraPropertyValue::Float(_)) => true,
|
Boolean(bool),
|
||||||
(CameraPropertyValue::Double(_), CameraPropertyValue::Double(_)) => true,
|
|
||||||
(CameraPropertyValue::String(_), CameraPropertyValue::String(_)) => true,
|
|
||||||
(CameraPropertyValue::Array(_), CameraPropertyValue::Array(_)) => true,
|
|
||||||
(CameraPropertyValue::EnumValue(_), CameraPropertyValue::EnumValue(_)) => true,
|
|
||||||
(CameraPropertyValue::Binary(_), CameraPropertyValue::Binary(_)) => true,
|
|
||||||
(CameraPropertyValue::Pair(..), CameraPropertyValue::Pair(..)) => true,
|
|
||||||
(CameraPropertyValue::Triple(..), CameraPropertyValue::Triple(..)) => true,
|
|
||||||
(CameraPropertyValue::Quadruple(..), CameraPropertyValue::Quadruple(..)) => true,
|
|
||||||
(CameraPropertyValue::KeyValue(..), CameraPropertyValue::KeyValue(..)) => true,
|
|
||||||
(_, _) => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for CameraPropertyValue {
|
#[derive(Clone, Debug, PartialEq, PartialOrd)]
|
||||||
fn eq(&self, other: &Self) -> bool {
|
pub enum ControlValue {
|
||||||
match &self {
|
Null,
|
||||||
CameraPropertyValue::Null => {
|
Integer(i64),
|
||||||
if let CameraPropertyValue::Null = other {
|
Bitmap(i64),
|
||||||
return true;
|
Float(f64),
|
||||||
}
|
String(String),
|
||||||
}
|
Boolean(bool),
|
||||||
CameraPropertyValue::Boolean(b) => {
|
KeyValue(String, ControlValuePrimitive),
|
||||||
if let CameraPropertyValue::Boolean(ob) = other {
|
|
||||||
return b == ob;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CameraPropertyValue::Integer(i) => {
|
|
||||||
if let CameraPropertyValue::Integer(oi) = other {
|
|
||||||
return i == oi;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CameraPropertyValue::LongInteger(i) => {
|
|
||||||
if let CameraPropertyValue::LongInteger(oi) = other {
|
|
||||||
return i == oi;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CameraPropertyValue::Float(f) => {
|
|
||||||
if let CameraPropertyValue::Float(of) = other {
|
|
||||||
return f == of;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CameraPropertyValue::Double(d) => {
|
|
||||||
if let CameraPropertyValue::Double(od) = other {
|
|
||||||
return d == od;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CameraPropertyValue::String(s) => {
|
|
||||||
if let CameraPropertyValue::String(os) = other {
|
|
||||||
return s == os;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CameraPropertyValue::Array(a) => {
|
|
||||||
if let CameraPropertyValue::Array(oa) = other {
|
|
||||||
return a == oa;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CameraPropertyValue::EnumValue(ev) => {
|
|
||||||
if let CameraPropertyValue::EnumValue(oev) = other {
|
|
||||||
return ev == oev;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CameraPropertyValue::Binary(bin) => {
|
|
||||||
if let CameraPropertyValue::Binary(obin) = other {
|
|
||||||
return bin == obin;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CameraPropertyValue::Pair(a, b) => {
|
|
||||||
if let CameraPropertyValue::Pair(oa, ob) = other {
|
|
||||||
return (a == oa) && (b == ob);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CameraPropertyValue::Triple(x, y, z) => {
|
|
||||||
if let CameraPropertyValue::Triple(ox, oy, oz) = other {
|
|
||||||
return (x == ox) && (y == oy) && (z == oz);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CameraPropertyValue::Quadruple(x, y, z, w) => {
|
|
||||||
if let CameraPropertyValue::Quadruple(ox, oy, oz, ow) = other {
|
|
||||||
return (x == ox) && (y == oy) && (z == oz) && (w == ow);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CameraPropertyValue::KeyValue(k, v) => {
|
|
||||||
if let CameraPropertyValue::KeyValue(ok, ov) = other {
|
|
||||||
return (k == ok) && (v == ov);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PartialOrd for CameraPropertyValue {
|
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
|
||||||
match self {
|
|
||||||
CameraPropertyValue::Null => match other {
|
|
||||||
CameraPropertyValue::Null => Some(Ordering::Greater),
|
|
||||||
_ => Some(Ordering::Less),
|
|
||||||
},
|
|
||||||
CameraPropertyValue::Boolean(b) => match other {
|
|
||||||
CameraPropertyValue::Null => Some(Ordering::Greater),
|
|
||||||
CameraPropertyValue::Boolean(o) => {
|
|
||||||
if o == b {
|
|
||||||
Some(Ordering::Equal)
|
|
||||||
} else if o {
|
|
||||||
Some(Ordering::Less)
|
|
||||||
} else {
|
|
||||||
Some(Ordering::Greater)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => Some(Ordering::Less),
|
|
||||||
},
|
|
||||||
CameraPropertyValue::Integer(int) => match other {
|
|
||||||
CameraPropertyValue::Null | CameraPropertyValue::Boolean(_) => {
|
|
||||||
Some(Ordering::Greater)
|
|
||||||
}
|
|
||||||
CameraPropertyValue::Integer(oth) => Some(int.cmp(oth)),
|
|
||||||
CameraPropertyValue::LongInteger(li) => {
|
|
||||||
let long = match i64::try_from(li) {
|
|
||||||
Ok(v) => v,
|
|
||||||
Err(_) => return None,
|
|
||||||
};
|
|
||||||
Some(int.cmp(&long))
|
|
||||||
}
|
|
||||||
_ => Some(Ordering::Less),
|
|
||||||
},
|
|
||||||
CameraPropertyValue::LongInteger(long) => match other {
|
|
||||||
CameraPropertyValue::Null | CameraPropertyValue::Boolean(_) => {
|
|
||||||
Some(Ordering::Greater)
|
|
||||||
}
|
|
||||||
CameraPropertyValue::Integer(oth) => Some(long.cmp(&(i128::from(oth)))),
|
|
||||||
CameraPropertyValue::LongInteger(o) => Some(long.cmp(o)),
|
|
||||||
_ => Some(Ordering::Less),
|
|
||||||
},
|
|
||||||
CameraPropertyValue::Float(fl) => match other {
|
|
||||||
CameraPropertyValue::Null
|
|
||||||
| CameraPropertyValue::Boolean(_)
|
|
||||||
| CameraPropertyValue::Integer(_)
|
|
||||||
| CameraPropertyValue::LongInteger(_) => Some(Ordering::Greater),
|
|
||||||
CameraPropertyValue::Float(f) => fl.partial_cmp(f),
|
|
||||||
CameraPropertyValue::Double(d) => f64::from(fl).partial_cmp(d),
|
|
||||||
_ => Some(Ordering::Less),
|
|
||||||
},
|
|
||||||
CameraPropertyValue::Double(d) => match other {
|
|
||||||
CameraPropertyValue::Null
|
|
||||||
| CameraPropertyValue::Boolean(_)
|
|
||||||
| CameraPropertyValue::Integer(_)
|
|
||||||
| CameraPropertyValue::LongInteger(_) => Some(Ordering::Greater),
|
|
||||||
CameraPropertyValue::Float(f) => d.partial_cmp(&(f64::from(f))),
|
|
||||||
CameraPropertyValue::Double(o) => d.partial_cmp(o),
|
|
||||||
_ => Some(Ordering::Less),
|
|
||||||
},
|
|
||||||
CameraPropertyValue::String(s) => match other {
|
|
||||||
CameraPropertyValue::Null
|
|
||||||
| CameraPropertyValue::Boolean(_)
|
|
||||||
| CameraPropertyValue::Integer(_)
|
|
||||||
| CameraPropertyValue::LongInteger(_)
|
|
||||||
| CameraPropertyValue::Float(_)
|
|
||||||
| CameraPropertyValue::Double(_) => Some(Ordering::Greater),
|
|
||||||
CameraPropertyValue::String(os) => s.partial_cmp(os),
|
|
||||||
_ => Some(Ordering::Less),
|
|
||||||
},
|
|
||||||
CameraPropertyValue::Array(a) => match other {
|
|
||||||
CameraPropertyValue::Null
|
|
||||||
| CameraPropertyValue::Boolean(_)
|
|
||||||
| CameraPropertyValue::Integer(_)
|
|
||||||
| CameraPropertyValue::LongInteger(_)
|
|
||||||
| CameraPropertyValue::Float(_)
|
|
||||||
| CameraPropertyValue::Double(_)
|
|
||||||
| CameraPropertyValue::String(_) => Some(Ordering::Greater),
|
|
||||||
CameraPropertyValue::Array(oa) => a.partial_cmp(oa),
|
|
||||||
_ => Some(Ordering::Less),
|
|
||||||
},
|
|
||||||
CameraPropertyValue::EnumValue(_) => match other {
|
|
||||||
CameraPropertyValue::Null
|
|
||||||
| CameraPropertyValue::Boolean(_)
|
|
||||||
| CameraPropertyValue::Integer(_)
|
|
||||||
| CameraPropertyValue::LongInteger(_)
|
|
||||||
| CameraPropertyValue::Float(_)
|
|
||||||
| CameraPropertyValue::Double(_)
|
|
||||||
| CameraPropertyValue::String(_)
|
|
||||||
| CameraPropertyValue::Array(_) => Some(Ordering::Greater),
|
|
||||||
CameraPropertyValue::EnumValue(_) => Some(Ordering::Equal),
|
|
||||||
_ => Some(Ordering::Less),
|
|
||||||
},
|
|
||||||
CameraPropertyValue::Binary(b) => match other {
|
|
||||||
CameraPropertyValue::Null
|
|
||||||
| CameraPropertyValue::Boolean(_)
|
|
||||||
| CameraPropertyValue::Integer(_)
|
|
||||||
| CameraPropertyValue::LongInteger(_)
|
|
||||||
| CameraPropertyValue::Float(_)
|
|
||||||
| CameraPropertyValue::Double(_)
|
|
||||||
| CameraPropertyValue::String(_)
|
|
||||||
| CameraPropertyValue::Array(_)
|
|
||||||
| CameraPropertyValue::EnumValue(_) => Some(Ordering::Greater),
|
|
||||||
CameraPropertyValue::Binary(ob) => b.partial_cmp(ob),
|
|
||||||
_ => Some(Ordering::Less),
|
|
||||||
},
|
|
||||||
// FIXME: implement this lole
|
|
||||||
CameraPropertyValue::Pair(_, _) => {
|
|
||||||
// match other {
|
|
||||||
// CameraPropertyValue::Null |
|
|
||||||
// CameraPropertyValue::Boolean(_) |
|
|
||||||
// CameraPropertyValue::Integer(_) |
|
|
||||||
// CameraPropertyValue::LongInteger(_) |
|
|
||||||
// CameraPropertyValue::Float(_) |
|
|
||||||
// CameraPropertyValue::Double(_) |
|
|
||||||
// CameraPropertyValue::String(_) |
|
|
||||||
// CameraPropertyValue::Array(_) |
|
|
||||||
// CameraPropertyValue::EnumValue(_) |
|
|
||||||
// CameraPropertyValue::Binary(_) => Some(Ordering::Greater),
|
|
||||||
// CameraPropertyValue::Pair(a, b) => {
|
|
||||||
// match a.partial_cmp(b) {
|
|
||||||
// Some(_) => {}
|
|
||||||
// None => {}
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// _ => Some(Ordering::Less)
|
|
||||||
// }
|
|
||||||
Some(Ordering::Equal)
|
|
||||||
}
|
|
||||||
CameraPropertyValue::Triple(_, _, _) => Some(Ordering::Equal),
|
|
||||||
CameraPropertyValue::Quadruple(_, _, _, _) => Some(Ordering::Equal),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for CameraPropertyValue {
|
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
||||||
write!(f, "{self:?}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! define_back_and_fourth_control {
|
|
||||||
($id_type:ty, { $( $control:expr [ $mode:expr, $value_type:expr, $value:expr ] => $control_id:expr, )* }, $id_to_str:expr, $str_to_id:expr) => {
|
|
||||||
pub struct ControlIntermediate {
|
|
||||||
pub mode: Option<$id_type>,
|
|
||||||
pub value_type: Option<$id_type>,
|
|
||||||
pub value: $id_type,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ControlIntermediate {
|
|
||||||
pub fn
|
|
||||||
}
|
|
||||||
|
|
||||||
// impl ControlIntermediate {
|
|
||||||
// pub fn into_control(native_ctrl: $id_type) -> (crate::properties::CameraPropertyId, Option<crate::properties::CameraPropertyFlag>) {
|
|
||||||
// match native_ctrl {
|
|
||||||
// $(
|
|
||||||
// $control_id => ($control, $flag)
|
|
||||||
// )*
|
|
||||||
// nc => (crate::properties::CameraPropertyId::Custom($id_to_str(nc)), None)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// pub fn into_native(property_id: &crate::properties::CameraPropertyId, flag: Option<crate::properties::CameraPropertyFlag>) -> Option<$id_type> {
|
|
||||||
// match (property_id, flag) {
|
|
||||||
// $(
|
|
||||||
// ($control, $flag) => Some($control_id),
|
|
||||||
// )*
|
|
||||||
// (crate::properties::CameraPropertyId::Custom(str_id), _) => $str_to_id(str_id),
|
|
||||||
// _ => None,
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
use crate::error::{NokhwaError, NokhwaResult};
|
use crate::error::{NokhwaError, NokhwaResult};
|
||||||
use crate::frame_buffer::FrameBuffer;
|
use crate::frame_buffer::FrameBuffer;
|
||||||
use flume::Receiver;
|
use flume::Receiver;
|
||||||
use futures::TryFutureExt;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
pub trait StreamInnerTrait {
|
pub trait StreamInnerTrait {
|
||||||
@@ -61,6 +60,8 @@ impl Stream {
|
|||||||
|
|
||||||
#[cfg(feature = "async")]
|
#[cfg(feature = "async")]
|
||||||
pub async fn await_frame(&self) -> NokhwaResult<FrameBuffer> {
|
pub async fn await_frame(&self) -> NokhwaResult<FrameBuffer> {
|
||||||
|
use futures::TryFutureExt;
|
||||||
|
|
||||||
if self.inner.receiver().is_disconnected() {
|
if self.inner.receiver().is_disconnected() {
|
||||||
return Err(NokhwaError::ReadFrameError(
|
return Err(NokhwaError::ReadFrameError(
|
||||||
"stream is disconnected!".to_string(),
|
"stream is disconnected!".to_string(),
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ use std::num::NonZeroI32;
|
|||||||
use std::ops::{Div, Rem};
|
use std::ops::{Div, Rem};
|
||||||
use num_rational::Rational32;
|
use num_rational::Rational32;
|
||||||
use crate::ranges::{SimpleRangeItem};
|
use crate::ranges::{SimpleRangeItem};
|
||||||
|
use num_traits::FromPrimitive;
|
||||||
|
|
||||||
/// Describes the index of the camera.
|
/// Describes the index of the camera.
|
||||||
/// - Index: A numbered index
|
/// - Index: A numbered index
|
||||||
@@ -247,6 +248,17 @@ impl FrameRate {
|
|||||||
pub fn denominator(&self) -> &i32 {
|
pub fn denominator(&self) -> &i32 {
|
||||||
self.rational.denom()
|
self.rational.denom()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn as_raw(&self) -> &Rational32 {
|
||||||
|
&self.rational
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn approximate_float(&self) -> Option<f32> {
|
||||||
|
let numerator_float = f32::from_i32(*self.numerator())?;
|
||||||
|
let denominator_float = f32::from_i32(*self.denominator())?;
|
||||||
|
|
||||||
|
Some(numerator_float / denominator_float)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for FrameRate {
|
impl Default for FrameRate {
|
||||||
@@ -299,7 +311,7 @@ impl From<Rational32> for FrameRate {
|
|||||||
|
|
||||||
/// This is a convenience struct that holds all information about the format of a webcam stream.
|
/// This is a convenience struct that holds all information about the format of a webcam stream.
|
||||||
/// It consists of a [`Resolution`], [`FrameFormat`], and a [`FrameRate`].
|
/// It consists of a [`Resolution`], [`FrameFormat`], and a [`FrameRate`].
|
||||||
#[derive(Copy, Clone, Debug, Hash, PartialEq, PartialOrd)]
|
#[derive(Copy, Clone, Debug, Hash, PartialEq, PartialOrd, Eq, Ord)]
|
||||||
#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
|
||||||
pub struct CameraFormat {
|
pub struct CameraFormat {
|
||||||
resolution: Resolution,
|
resolution: Resolution,
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ use nokhwa_core::{
|
|||||||
use std::{ffi::CString, sync::Arc};
|
use std::{ffi::CString, sync::Arc};
|
||||||
|
|
||||||
use std::{borrow::Cow, collections::HashMap};
|
use std::{borrow::Cow, collections::HashMap};
|
||||||
use nokhwa_core::properties::{CameraControl, ControlValueSetter, KnownCameraControl};
|
use nokhwa_core::properties::{CameraControl, ControlValue, KnownCameraControl};
|
||||||
|
|
||||||
/// The backend struct that interfaces with V4L2.
|
/// The backend struct that interfaces with V4L2.
|
||||||
/// To see what this does, please see [`CaptureTrait`].
|
/// To see what this does, please see [`CaptureTrait`].
|
||||||
@@ -231,7 +231,7 @@ impl CaptureTrait for AVFoundationCaptureDevice {
|
|||||||
fn set_camera_control(
|
fn set_camera_control(
|
||||||
&mut self,
|
&mut self,
|
||||||
id: KnownCameraControl,
|
id: KnownCameraControl,
|
||||||
value: ControlValueSetter,
|
value: ControlValue,
|
||||||
) -> Result<(), NokhwaError> {
|
) -> Result<(), NokhwaError> {
|
||||||
self.device.lock()?;
|
self.device.lock()?;
|
||||||
let res = self.device.set_control(id, value);
|
let res = self.device.set_control(id, value);
|
||||||
@@ -463,7 +463,7 @@ impl CaptureTrait for AVFoundationCaptureDevice {
|
|||||||
fn set_camera_control(
|
fn set_camera_control(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: KnownCameraControl,
|
_: KnownCameraControl,
|
||||||
_: ControlValueSetter,
|
_: ControlValue,
|
||||||
) -> Result<(), NokhwaError> {
|
) -> Result<(), NokhwaError> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use serde::{de, Serialize};
|
|||||||
use wasm_bindgen_futures::JsFuture;
|
use wasm_bindgen_futures::JsFuture;
|
||||||
use web_sys::{window, MediaDeviceInfo, MediaDevices, MediaStream, MediaStreamConstraints, MediaStreamTrack, MediaTrackConstraints, Navigator};
|
use web_sys::{window, MediaDeviceInfo, MediaDevices, MediaStream, MediaStreamConstraints, MediaStreamTrack, MediaTrackConstraints, Navigator};
|
||||||
use nokhwa_core::frame_buffer::FrameBuffer;
|
use nokhwa_core::frame_buffer::FrameBuffer;
|
||||||
use nokhwa_core::properties::{CameraControl, ControlValueSetter, KnownCameraControl};
|
use nokhwa_core::properties::{CameraControl, ControlValue, KnownCameraControl};
|
||||||
use nokhwa_core::error::NokhwaError;
|
use nokhwa_core::error::NokhwaError;
|
||||||
use nokhwa_core::frame_format::FrameFormat;
|
use nokhwa_core::frame_format::FrameFormat;
|
||||||
use nokhwa_core::traits::{AsyncCaptureTrait, AsyncOpenCaptureTrait, CaptureTrait, OpenCaptureTrait};
|
use nokhwa_core::traits::{AsyncCaptureTrait, AsyncOpenCaptureTrait, CaptureTrait, OpenCaptureTrait};
|
||||||
@@ -360,7 +360,7 @@ impl CaptureTrait for BrowserCaptureDevice {
|
|||||||
fn set_camera_control(
|
fn set_camera_control(
|
||||||
&mut self,
|
&mut self,
|
||||||
id: KnownCameraControl,
|
id: KnownCameraControl,
|
||||||
value: ControlValueSetter,
|
value: ControlValue,
|
||||||
) -> Result<(), NokhwaError> {
|
) -> Result<(), NokhwaError> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
@@ -414,7 +414,7 @@ impl AsyncCaptureTrait for BrowserCaptureDevice {
|
|||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn set_camera_control_async(&mut self, id: KnownCameraControl, value: ControlValueSetter) -> Result<(), NokhwaError> {
|
async fn set_camera_control_async(&mut self, id: KnownCameraControl, value: ControlValue) -> Result<(), NokhwaError> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ use nokhwa_core::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
use std::{borrow::Cow, collections::HashMap};
|
use std::{borrow::Cow, collections::HashMap};
|
||||||
use nokhwa_core::properties::{all_known_camera_controls, CameraControl, ControlValueSetter, KnownCameraControl};
|
use nokhwa_core::properties::{all_known_camera_controls, CameraControl, ControlValue, KnownCameraControl};
|
||||||
|
|
||||||
/// The backend that deals with Media Foundation on Windows.
|
/// The backend that deals with Media Foundation on Windows.
|
||||||
/// To see what this does, please see [`CaptureTrait`].
|
/// To see what this does, please see [`CaptureTrait`].
|
||||||
@@ -229,7 +229,7 @@ impl CaptureTrait for MediaFoundationCaptureDevice {
|
|||||||
fn set_camera_control(
|
fn set_camera_control(
|
||||||
&mut self,
|
&mut self,
|
||||||
id: KnownCameraControl,
|
id: KnownCameraControl,
|
||||||
value: ControlValueSetter,
|
value: ControlValue,
|
||||||
) -> Result<(), NokhwaError> {
|
) -> Result<(), NokhwaError> {
|
||||||
self.inner.set_control(id, value)
|
self.inner.set_control(id, value)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ use opencv::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
use std::{borrow::Cow, collections::HashMap};
|
use std::{borrow::Cow, collections::HashMap};
|
||||||
use nokhwa_core::properties::{CameraControl, ControlValueDescription, ControlValueSetter, KnownCameraControl};
|
use nokhwa_core::properties::{CameraControl, ControlValueDescription, ControlValue, KnownCameraControl};
|
||||||
|
|
||||||
/// Attempts to convert a [`KnownCameraControl`] into a `OpenCV` video capture property.
|
/// Attempts to convert a [`KnownCameraControl`] into a `OpenCV` video capture property.
|
||||||
/// If the associated control is not found, this will return `Err`
|
/// If the associated control is not found, this will return `Err`
|
||||||
@@ -434,12 +434,12 @@ impl CaptureTrait for OpenCvCaptureDevice {
|
|||||||
fn set_camera_control(
|
fn set_camera_control(
|
||||||
&mut self,
|
&mut self,
|
||||||
id: KnownCameraControl,
|
id: KnownCameraControl,
|
||||||
value: ControlValueSetter,
|
value: ControlValue,
|
||||||
) -> Result<(), NokhwaError> {
|
) -> Result<(), NokhwaError> {
|
||||||
let control_val = match value {
|
let control_val = match value {
|
||||||
ControlValueSetter::Integer(i) => i as f64,
|
ControlValue::Integer(i) => i as f64,
|
||||||
ControlValueSetter::Float(f) => f,
|
ControlValue::Float(f) => f,
|
||||||
ControlValueSetter::Boolean(b) => u8::from(b) as f64,
|
ControlValue::Boolean(b) => u8::from(b) as f64,
|
||||||
val => {
|
val => {
|
||||||
return Err(NokhwaError::SetPropertyError {
|
return Err(NokhwaError::SetPropertyError {
|
||||||
property: "Camera Control".to_string(),
|
property: "Camera Control".to_string(),
|
||||||
|
|||||||
+2
-2
@@ -28,7 +28,7 @@ use nokhwa_core::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
use std::{borrow::Cow, collections::HashMap};
|
use std::{borrow::Cow, collections::HashMap};
|
||||||
use nokhwa_core::properties::{CameraControl, ControlValueSetter, KnownCameraControl};
|
use nokhwa_core::properties::{CameraControl, ControlValue, KnownCameraControl};
|
||||||
|
|
||||||
/// The main `Camera` struct. This is the struct that abstracts over all the backends, providing a simplified interface for use.
|
/// The main `Camera` struct. This is the struct that abstracts over all the backends, providing a simplified interface for use.
|
||||||
pub struct Camera {
|
pub struct Camera {
|
||||||
@@ -123,7 +123,7 @@ impl CaptureTrait for Camera {
|
|||||||
fn set_camera_control(
|
fn set_camera_control(
|
||||||
&mut self,
|
&mut self,
|
||||||
id: KnownCameraControl,
|
id: KnownCameraControl,
|
||||||
value: ControlValueSetter,
|
value: ControlValue,
|
||||||
) -> Result<(), NokhwaError> {
|
) -> Result<(), NokhwaError> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -31,7 +31,7 @@ use std::{
|
|||||||
Arc, Mutex,
|
Arc, Mutex,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use nokhwa_core::properties::{CameraControl, ControlValueSetter, KnownCameraControl};
|
use nokhwa_core::properties::{CameraControl, ControlValue, KnownCameraControl};
|
||||||
|
|
||||||
type AtomicLock<T> = Arc<Mutex<T>>;
|
type AtomicLock<T> = Arc<Mutex<T>>;
|
||||||
pub type CallbackFn = fn(
|
pub type CallbackFn = fn(
|
||||||
@@ -420,14 +420,14 @@ impl CallbackCamera {
|
|||||||
|
|
||||||
/// Sets the control to `control` in the camera.
|
/// Sets the control to `control` in the camera.
|
||||||
/// Usually, the pipeline is calling [`camera_control()`](crate::camera_traits::CaptureTrait::camera_control), getting a camera control that way
|
/// Usually, the pipeline is calling [`camera_control()`](crate::camera_traits::CaptureTrait::camera_control), getting a camera control that way
|
||||||
/// then calling [`value()`](nokhwa_core::properties::CameraControl::value()) to get a [`ControlValueSetter`](nokhwa_core::properties::ControlValueSetter) and setting the value that way.
|
/// then calling [`value()`](nokhwa_core::properties::CameraControl::value()) to get a [`ControlValueSetter`](nokhwa_core::properties::ControlValue) and setting the value that way.
|
||||||
/// # Errors
|
/// # Errors
|
||||||
/// If the `control` is not supported, the value is invalid (less than min, greater than max, not in step), or there was an error setting the control,
|
/// If the `control` is not supported, the value is invalid (less than min, greater than max, not in step), or there was an error setting the control,
|
||||||
/// this will error.
|
/// this will error.
|
||||||
pub fn set_camera_control(
|
pub fn set_camera_control(
|
||||||
&mut self,
|
&mut self,
|
||||||
id: KnownCameraControl,
|
id: KnownCameraControl,
|
||||||
control: ControlValueSetter,
|
control: ControlValue,
|
||||||
) -> Result<(), NokhwaError> {
|
) -> Result<(), NokhwaError> {
|
||||||
self.camera
|
self.camera
|
||||||
.lock()
|
.lock()
|
||||||
|
|||||||
Reference in New Issue
Block a user