new controls

This commit is contained in:
l1npengtul
2024-10-02 22:10:31 +09:00
parent d5eab8bbf2
commit 4adf68c85f
26 changed files with 2004 additions and 1105 deletions
+5 -2
View File
@@ -40,7 +40,7 @@ version = "22"
optional = true
[dependencies.opencv]
version = "0.92"
version = "0.93"
default-features = false
optional = true
@@ -57,8 +57,11 @@ version = "0.6"
optional = true
[dependencies.yuvutils-rs]
version = "0.3"
version = "0.4"
optional = true
[dependencies.rgb]
version = "0.8"
[package.metadata.docs.rs]
features = ["docs-features"]
File diff suppressed because it is too large Load Diff
+3 -1
View File
@@ -49,10 +49,12 @@ impl<D> Decoder for GeneralPurposeDecoder<D> where D: PixelWithColorType {
// already decoded
FrameFormat::Rgb8 => PixelFormat::Rgb,
FrameFormat::RgbA8 => {
PixelFormat::Rgba
PixelFormat::Rgb
}
_ => return Err(()),
};
dcv_color_primitives::convert_image(buffer.resolution().width(), buffer.resolution().height(), )
}
}
+1
View File
@@ -16,6 +16,7 @@
use crate::{frame_format::FrameFormat, types::ApiBackend};
use thiserror::Error;
use crate::ranges::RangeValidationResult;
/// All errors in `nokhwa`.
#[allow(clippy::module_name_repetitions)]
+3 -2
View File
@@ -4,9 +4,10 @@ use std::{
};
use crate::{
frame_format::FrameFormat,
types::{CameraFormat, Resolution, FrameRate, Range},
traits::Distance
traits::Distance,
types::{CameraFormat, FrameRate, Resolution}
};
use crate::ranges::Range;
#[derive(Copy, Clone, Debug, PartialOrd, PartialEq)]
enum ClosestType {
+2
View File
@@ -30,3 +30,5 @@ pub mod traits;
pub mod types;
pub mod decoders;
pub mod utils;
pub mod ranges;
pub mod controls;
+516
View File
@@ -0,0 +1,516 @@
use std::collections::HashMap;
use core::fmt::{ Debug, Display, Formatter};
use std::collections::hash_map::Keys;
use std::hash::Hash;
use std::ops::{Div, Sub};
use crate::error::NokhwaError;
/// Failed to validate.
#[derive(Copy, Clone, Debug, Default, Hash, Ord, PartialOrd, Eq, PartialEq)]
pub struct RangeValidationFailure;
/// A range type that can be validated.
pub trait ValidatableRange {
/// Input type to validate.
type Validation;
/// Validates the value.
fn validate(&self, value: Self::Validation) -> Result<(), RangeValidationFailure>;
}
/// Creates a range of values.
///
/// Inclusive by default.
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
pub struct Range<T>
{
minimum: Option<T>,
lower_inclusive: bool,
maximum: Option<T>,
upper_inclusive: bool,
preferred: T,
}
impl<T> Range<T>
where
T: Copy + Clone + Debug + PartialOrd + PartialEq,
{
/// Create an upper and lower inclusive [`Range`]
pub fn new(preferred: T, min: Option<T>, max: Option<T>) -> Self {
Self {
minimum: min,
lower_inclusive: true,
maximum: max,
upper_inclusive: true,
preferred,
}
}
pub fn with_inclusive(
preferred: T,
min: Option<T>,
lower_inclusive: bool,
max: Option<T>,
upper_inclusive: bool,
) -> Self {
Self {
minimum: min,
lower_inclusive,
maximum: max,
upper_inclusive,
preferred,
}
}
pub fn exact(preferred: T) -> Self {
Self {
minimum: None,
lower_inclusive: true,
maximum: None,
upper_inclusive: true,
preferred,
}
}
pub fn set_minimum(&mut self, minimum: Option<T>) {
self.minimum = minimum;
}
pub fn set_lower_inclusive(&mut self, lower_inclusive: bool) {
self.lower_inclusive = lower_inclusive;
}
pub fn set_maximum(&mut self, maximum: Option<T>) {
self.maximum = maximum;
}
pub fn set_upper_inclusive(&mut self, upper_inclusive: bool) {
self.upper_inclusive = upper_inclusive;
}
pub fn set_preferred(&mut self, preferred: T) {
self.preferred = preferred;
}
pub fn minimum(&self) -> Option<T> {
self.minimum
}
pub fn lower_inclusive(&self) -> bool {
self.lower_inclusive
}
pub fn maximum(&self) -> Option<T> {
self.maximum
}
pub fn upper_inclusive(&self) -> bool {
self.upper_inclusive
}
pub fn preferred(&self) -> T {
self.preferred
}
}
impl<T> ValidatableRange for Range<T> where T: PartialEq + PartialOrd {
type Validation = T;
fn validate(&self, value: Self::Validation) -> Result<(), RangeValidationFailure> {
num_range_validate(self.minimum.as_ref(), self.maximum.as_ref(), &self.preferred, self.lower_inclusive, self.upper_inclusive, &value)
}
}
impl<T> Default for Range<T>
where
T: Default,
{
fn default() -> Self {
Range {
minimum: None,
lower_inclusive: true,
maximum: None,
upper_inclusive: true,
preferred: T::default(),
}
}
}
impl<T> Display for Range<T> where T: Debug {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let lower_inclusive_char = bool_to_inclusive_char(self.lower_inclusive, false);
let upper_inclusive_char = bool_to_inclusive_char(self.upper_inclusive, true);
let default = default_to_string(&self.preferred);
write!(f, "Range: {lower_inclusive_char}{}, {}{upper_inclusive_char}, Preferred: {default}", self.minimum, self.maximum)
}
}
#[derive(Copy, Clone, Debug, PartialOrd, PartialEq)]
pub struct IndicatedRange<T> where T: Copy + Clone + Debug + PartialOrd + PartialEq {
minimum: T,
lower_inclusive: bool,
maximum: T,
upper_inclusive: bool,
step: Option<T>,
default: Option<T>,
}
impl<T> IndicatedRange<T>
where
T: Copy + Clone + Debug + PartialOrd + PartialEq
{
pub fn new(minimum: T, lower_inclusive: bool, maximum: T, upper_inclusive: bool, step: Option<T>, default: Option<T>) -> Self {
Self { minimum, lower_inclusive, maximum, upper_inclusive, step, default }
}
pub fn minimum(&self) -> T {
self.minimum
}
pub fn lower_inclusive(&self) -> bool {
self.lower_inclusive
}
pub fn maximum(&self) -> T {
self.maximum
}
pub fn upper_inclusive(&self) -> bool {
self.upper_inclusive
}
pub fn step(&self) -> Option<T> {
self.step
}
pub fn default_value(&self) -> Option<T> {
self.default
}
}
impl<T> ValidatableRange for IndicatedRange<T> where T: Copy + PartialEq + PartialOrd + Div<Output = T> + Sub<Output = T> + Number {
type Validation = T;
fn validate(&self, value: Self::Validation) -> Result<(), RangeValidationFailure> {
if let Some(step) = &self.step {
let prepared_value = value - &self.minimum;
// We can check the step if we subtract the value from the minimum value
// then see if the remainder of prepared value and step is zero.
// e.g. 4, 12, value is 7, step is 3
// 7 - 4 = 3
// 3 % 3 = 0 Valid!
if prepared_value % step != 0 {
return Err(RangeValidationFailure::default())
}
}
num_range_validate(self.minimum.as_ref(), self.maximum.as_ref(), &self.default, self.lower_inclusive, self.upper_inclusive, &value)
}
}
impl<T> Display for IndicatedRange<T> where T: Debug {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let lower_inclusive_char = bool_to_inclusive_char(self.lower_inclusive, false);
let upper_inclusive_char = bool_to_inclusive_char(self.upper_inclusive, true);
let default = default_to_string(&self.default);
let step = default_to_string(&self.step);
// Ex) IndicatedRange: (5, 19], Step: 3, Default: 8
write!(f, "IndicatedRange: {lower_inclusive_char}{}, {}{upper_inclusive_char}, Step: {step}, Default: {default}", self.minimum, self.maximum)
}
}
#[derive(Clone, Debug, PartialOrd, PartialEq)]
pub struct NonCopyRange<T> where T: Clone + Debug + PartialOrd + PartialEq {
minimum: T,
lower_inclusive: bool,
maximum: T,
upper_inclusive: bool,
step: Option<T>,
default: Option<T>,
}
impl<T> NonCopyRange<T>
where
T: Clone + Debug + PartialOrd + PartialEq
{
pub fn new(minimum: T, lower_inclusive: bool, maximum: T, upper_inclusive: bool, step: Option<T>, default: Option<T>) -> Self {
Self { minimum, lower_inclusive, maximum, upper_inclusive, step, default }
}
pub fn minimum(&self) -> &T {
&self.minimum
}
pub fn lower_inclusive(&self) -> bool {
self.lower_inclusive
}
pub fn maximum(&self) -> &T {
&self.maximum
}
pub fn upper_inclusive(&self) -> bool {
self.upper_inclusive
}
pub fn step(&self) -> Option<&T> {
self.step.as_ref()
}
pub fn default_value(&self) -> Option<&T> {
self.default.as_ref()
}
}
impl<T> ValidatableRange for NonCopyRange<T> where T: Clone + PartialEq + PartialOrd + Div<Output = T> + Sub<Output = T> {
type Validation = T;
fn validate(&self, value: Self::Validation) -> Result<(), RangeValidationFailure> {
if let Some(step) = &self.step {
let prepared_value = value.clone() - &self.minimum;
// We can check the step if we subtract the value from the minimum value
// then see if the remainder of prepared value and step is zero.
// e.g. 4, 12, value is 7, step is 3
// 7 - 4 = 3
// 3 % 3 = 0 Valid!
if prepared_value % step != 0 {
return Err(RangeValidationFailure::default())
}
}
num_range_validate(self.minimum.as_ref(), self.maximum.as_ref(), &self.default, self.lower_inclusive, self.upper_inclusive, &value)
}
}
impl<T> Display for IndicatedRange<T> where T: Debug {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let lower_inclusive_char = bool_to_inclusive_char(self.lower_inclusive, false);
let upper_inclusive_char = bool_to_inclusive_char(self.upper_inclusive, true);
let default = default_to_string(&self.default);
let step = default_to_string(&self.step);
// Ex) IndicatedRange: (5, 19], Step: 3, Default: 8
write!(f, "IndicatedRange: {lower_inclusive_char}{}, {}{upper_inclusive_char}, Step: {step}, Default: {default}", self.minimum, self.maximum)
}
}
#[derive(Clone, Debug)]
pub struct Options<T> where T: Clone + Debug {
default: Option<T>,
available: Vec<T>,
}
impl<T> Options<T>
where
T: Clone + Debug + PartialEq
{
pub fn new(values: Vec<T>, default_value: T) -> Self {
Self {
default: default_value,
available: values,
}
}
pub fn default_value(&self) -> Option<&T> {
self.default.as_ref()
}
pub fn available(&self) -> &[T] {
&self.available
}
}
impl<T> ValidatableRange for Options<T> where T: PartialEq {
type Validation = T;
fn validate(&self, value: Self::Validation) -> Result<(), RangeValidationFailure> {
if self.available.contains(value) {
return Ok(());
}
Err(RangeValidationFailure::default())
}
}
impl<T> Display for Options<T> where T: Debug {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let default = default_to_string(&self.default);
write!(f, "Options: Available {:?}, Default: {default}", self.available)
}
}
#[derive(Clone, Debug)]
pub struct KeyValue<K, V> where K: Clone + Debug + Hash + Eq, V: Clone + Debug {
defaults: HashMap<K, V>,
}
impl<K, V> KeyValue<K, V>
where
K: Clone + Debug + Hash + Eq,
V: Clone + Debug
{
pub fn new(default: HashMap<K, V>) -> Self {
Self {
defaults: default,
}
}
pub fn available_keys(&self) -> &Keys<'_, K, V> {
&self.defaults.keys()
}
pub fn by_key(&self, key: &K) -> Option<&V> {
self.defaults.get(key)
}
}
impl<T> ValidatableRange for KeyValue<T, _> where T: Eq + Hash {
type Validation = T;
fn validate(&self, value: Self::Validation) -> Result<(), RangeValidationFailure> {
if self.defaults.contains_key(&value) {
return Ok(())
}
Err(RangeValidationFailure::default())
}
}
impl<K, V> Display for KeyValue<K, V> where K: Debug, V: Debug {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
// TODO: pretty print?
write!(f, "Key Value Pairs: {:?}", self.defaults)
}
}
#[derive(Clone, Debug)]
pub struct ArrayRange<T> where T: Clone + Debug {
appendable_options: Vec<T>,
default_options: Vec<T>,
}
impl<T> ArrayRange<T> where T: Clone + Debug + PartialEq {
pub fn new(appendable: Vec<T>, default: Vec<T>) -> Result<Self, NokhwaError> {
for option in &default {
if !appendable.contains(option) {
return Err(NokhwaError::StructureError { structure: "ArrayRange".to_string(), error: "Attempted to add an undependable option to default option - ILLEGAL! - If you got this while using a driver, this is a bug! Please report to https://github.com/l1npengtul/nokhwa/issues!".to_string() })
}
}
Ok(Self {
appendable_options: appendable,
default_options: default,
})
}
pub fn appendable_options(&self) -> &[T] {
&self.appendable_options
}
pub fn default_options(&self) -> &[T] {
&self.default_options
}
}
impl<T> ValidatableRange for ArrayRange<T> where T: PartialEq {
type Validation = T;
fn validate(&self, value: Self::Validation) -> Result<(), RangeValidationFailure> {
if self.appendable_options.contains(value) {
return Ok(());
}
Err(RangeValidationFailure::default())
}
}
impl<T> Display for ArrayRange<T> where T: Debug {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "ArrayRange: Available Options: {:?}, Default: {:?}", self.appendable_options, self.default_options)
}
}
#[derive(Clone, Debug)]
pub struct Simple<T> where T: Clone + Debug {
default: Option<T>
}
impl<T> Simple<T> where T: Clone + Debug {
pub fn new(default: Option<T>) -> Self {
Self {
default,
}
}
pub fn default_value(&self) -> Option<&T> {
self.default.as_ref()
}
}
impl<T> ValidatableRange for Simple<T> {
type Validation = T;
fn validate(&self, _: Self::Validation) -> Result<(), RangeValidationFailure> {
Ok(())
}
}
impl<T> Display for Simple<T> where T: Debug {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let default = default_to_string(&self.default);
write!(f, "Simple (Any Value): Default Value: {default}")
}
}
fn bool_to_inclusive_char(inclusive: bool, upper: bool) -> char {
match inclusive {
true => if upper { ']' } else { '[' },
false => if upper { ')' } else { '(' },
}
}
fn default_to_string<T>(default: &Option<T>) -> String where T: Debug {
match default {
Some(v) => {
format!("{v:?}")
}
None => String::from("None"),
}
}
fn num_range_validate<T>(minimum: Option<&T>, maximum: Option<&T>, default: &T, lower_inclusive: bool, upper_inclusive: bool, value: &T) -> Result<(), RangeValidationFailure> where T: PartialEq + PartialOrd {
if value == default {
return Ok(())
}
if let Some(min) = minimum {
let test = if lower_inclusive {
min <= value
} else {
min < value
};
if test {
return Err(RangeValidationFailure::default());
}
}
if let Some(max) = maximum {
let test = if upper_inclusive {
max >= value
} else {
max > value
};
if test {
return Err(RangeValidationFailure::default());
}
}
Ok(())
}
trait Number {}
macro_rules! impl_num {
( $($n:ty, )* ) => {
{
$(
impl Number for $n {}
)*
}
};
}
impl_num!( i8, u8, i16, u16, i32, u32, i64, u64, i128, u128, f32, f64, );
+2 -1
View File
@@ -16,10 +16,11 @@
use crate::{
buffer::Buffer, error::NokhwaError, format_request::FormatRequest, types::{
ApiBackend, CameraControl, CameraFormat, CameraIndex, CameraInfo, ControlValueSetter, KnownCameraControl, Resolution
ApiBackend, CameraFormat, CameraIndex, CameraInfo, Resolution
}
};
use std::{borrow::Cow, collections::HashMap};
use crate::controls::{CameraControl, ControlValueSetter, KnownCameraControl};
use crate::frame_format::FrameFormat;
use crate::types::FrameRate;
+4 -823
View File
@@ -5,147 +5,17 @@ use crate::{
#[cfg(feature = "serialize")]
use serde::{Deserialize, Serialize};
use std::{
borrow::Borrow, cmp::Ordering, fmt::{
borrow::Borrow, cmp::Ordering, collections::HashSet, fmt::{
Debug,
Display,
Formatter
}, hash::{Hash, Hasher}, ops::{Add, Deref, DerefMut, Sub}
};
use std::collections::HashMap;
use crate::controls::{CameraControl, CameraPropertyFlag, KnownCameraControl};
use crate::ranges::Range;
use crate::traits::Distance;
/// Creates a range of values.
///
/// Inclusive by default.
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
pub struct Range<T>
{
minimum: Option<T>,
lower_inclusive: bool,
maximum: Option<T>,
upper_inclusive: bool,
preferred: T,
}
impl<T> Range<T>
where
T: Copy + Clone + Debug + PartialOrd + PartialEq,
{
/// Create an upper and lower inclusive [`Range`]
pub fn new(preferred: T, min: Option<T>, max: Option<T>) -> Self {
Self {
minimum: min,
lower_inclusive: true,
maximum: max,
upper_inclusive: true,
preferred,
}
}
pub fn with_inclusive(
preferred: T,
min: Option<T>,
lower_inclusive: bool,
max: Option<T>,
upper_inclusive: bool,
) -> Self {
Self {
minimum: min,
lower_inclusive,
maximum: max,
upper_inclusive,
preferred,
}
}
pub fn exact(preferred: T) -> Self {
Self {
minimum: None,
lower_inclusive: true,
maximum: None,
upper_inclusive: true,
preferred,
}
}
pub fn in_range(&self, item: T) -> bool {
if item == self.preferred {
return true
}
if let Some(min) = self.minimum {
let test = if self.lower_inclusive {
min >= item
} else {
min > item
};
if test {
return false;
}
}
if let Some(max) = self.maximum {
let test = if self.lower_inclusive {
max <= item
} else {
max < item
};
if test {
return false;
}
}
true
}
pub fn set_minimum(&mut self, minimum: Option<T>) {
self.minimum = minimum;
}
pub fn set_lower_inclusive(&mut self, lower_inclusive: bool) {
self.lower_inclusive = lower_inclusive;
}
pub fn set_maximum(&mut self, maximum: Option<T>) {
self.maximum = maximum;
}
pub fn set_upper_inclusive(&mut self, upper_inclusive: bool) {
self.upper_inclusive = upper_inclusive;
}
pub fn set_preferred(&mut self, preferred: T) {
self.preferred = preferred;
}
pub fn minimum(&self) -> Option<T> {
self.minimum
}
pub fn lower_inclusive(&self) -> bool {
self.lower_inclusive
}
pub fn maximum(&self) -> Option<T> {
self.maximum
}
pub fn upper_inclusive(&self) -> bool {
self.upper_inclusive
}
pub fn preferred(&self) -> T {
self.preferred
}
}
impl<T> Default for Range<T>
where
T: Default,
{
fn default() -> Self {
Range {
minimum: None,
lower_inclusive: true,
maximum: None,
upper_inclusive: true,
preferred: T::default(),
}
}
}
/// Describes the index of the camera.
/// - Index: A numbered index
@@ -626,456 +496,6 @@ impl Display for CameraInfo {
}
}
/// The list of known camera controls to the library. <br>
/// These can control the picture brightness, etc. <br>
/// Note that not all backends/devices support all these. Run [`supported_camera_controls()`](crate::traits::CaptureTrait::camera_controls) to see which ones can be set.
#[derive(Copy, Clone, Debug, Hash, Ord, PartialOrd, Eq, PartialEq)]
#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
pub enum KnownCameraControl {
Brightness,
Contrast,
Hue,
Saturation,
Sharpness,
Gamma,
WhiteBalance,
BacklightComp,
Gain,
Pan,
Tilt,
Zoom,
Exposure,
Iris,
Focus,
Facing,
/// Other camera control. Listed is the ID.
/// Wasteful, however is needed for a unified API across Windows, Linux, and MacOSX due to Microsoft's usage of GUIDs.
///
/// THIS SHOULD ONLY BE USED WHEN YOU KNOW THE PLATFORM THAT YOU ARE RUNNING ON.
Other(u128),
}
/// All camera controls in an array.
#[must_use]
pub const fn all_known_camera_controls() -> &'static [KnownCameraControl] {
&[
KnownCameraControl::Brightness,
KnownCameraControl::Contrast,
KnownCameraControl::Hue,
KnownCameraControl::Saturation,
KnownCameraControl::Sharpness,
KnownCameraControl::Gamma,
KnownCameraControl::WhiteBalance,
KnownCameraControl::BacklightComp,
KnownCameraControl::Gain,
KnownCameraControl::Pan,
KnownCameraControl::Tilt,
KnownCameraControl::Zoom,
KnownCameraControl::Exposure,
KnownCameraControl::Iris,
KnownCameraControl::Focus,
KnownCameraControl::Facing,
]
}
impl Display for KnownCameraControl {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}", &self)
}
}
/// This tells you weather a [`KnownCameraControl`] is automatically managed by the OS/Driver
/// or manually managed by you, the programmer.
#[derive(Copy, Clone, Debug, Hash, Ord, PartialOrd, Eq, PartialEq)]
#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
pub enum KnownCameraControlFlag {
Automatic,
Manual,
Continuous,
ReadOnly,
WriteOnly,
Volatile,
Disabled,
}
impl Display for KnownCameraControlFlag {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{self:?}")
}
}
/// The values for a [`CameraControl`].
///
/// This provides a wide range of values that can be used to control a camera.
#[derive(Clone, Debug, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
pub enum ControlValueDescription {
None,
Integer {
value: i64,
default: i64,
step: i64,
},
IntegerRange {
min: i64,
max: i64,
value: i64,
step: i64,
default: i64,
},
Float {
value: f64,
default: f64,
step: f64,
},
FloatRange {
min: f64,
max: f64,
value: f64,
step: f64,
default: f64,
},
Boolean {
value: bool,
default: bool,
},
String {
value: String,
default: Option<String>,
},
Bytes {
value: Vec<u8>,
default: Vec<u8>,
},
KeyValuePair {
key: i128,
value: i128,
default: (i128, i128),
},
Point {
value: (f64, f64),
default: (f64, f64),
},
Enum {
value: i64,
possible: Vec<i64>,
default: i64,
},
RGB {
value: (f64, f64, f64),
max: (f64, f64, f64),
default: (f64, f64, f64),
},
StringList {
value: String,
availible: Vec<String>,
},
}
impl ControlValueDescription {
/// Get the value of this [`ControlValueDescription`]
#[must_use]
pub fn value(&self) -> ControlValueSetter {
match self {
ControlValueDescription::None => ControlValueSetter::None,
ControlValueDescription::Integer { value, .. }
| ControlValueDescription::IntegerRange { value, .. } => {
ControlValueSetter::Integer(*value)
}
ControlValueDescription::Float { value, .. }
| ControlValueDescription::FloatRange { value, .. } => {
ControlValueSetter::Float(*value)
}
ControlValueDescription::Boolean { value, .. } => ControlValueSetter::Boolean(*value),
ControlValueDescription::String { value, .. } => {
ControlValueSetter::String(value.clone())
}
ControlValueDescription::Bytes { value, .. } => {
ControlValueSetter::Bytes(value.clone())
}
ControlValueDescription::KeyValuePair { key, value, .. } => {
ControlValueSetter::KeyValue(*key, *value)
}
ControlValueDescription::Point { value, .. } => {
ControlValueSetter::Point(value.0, value.1)
}
ControlValueDescription::Enum { value, .. } => ControlValueSetter::EnumValue(*value),
ControlValueDescription::RGB { value, .. } => {
ControlValueSetter::RGB(value.0, value.1, value.2)
}
ControlValueDescription::StringList { value, .. } => {
ControlValueSetter::StringList(value.clone())
}
}
}
/// Verifies if the [setter](ControlValueSetter) is valid for the provided [`ControlValueDescription`].
/// - `true` => Is valid.
/// - `false` => Is not valid.
///
/// If the step is 0, it will automatically return `true`.
#[must_use]
pub fn verify_setter(&self, setter: &ControlValueSetter) -> bool {
match self {
ControlValueDescription::None => setter.as_none().is_some(),
ControlValueDescription::Integer {
value,
default,
step,
} => {
if *step == 0 {
return true;
}
match setter.as_integer() {
Some(i) => (i + default) % step == 0 || (i + value) % step == 0,
None => false,
}
}
ControlValueDescription::IntegerRange {
min,
max,
value,
step,
default,
} => {
if *step == 0 {
return true;
}
match setter.as_integer() {
Some(i) => {
((i + default) % step == 0 || (i + value) % step == 0)
&& i >= min
&& i <= max
}
None => false,
}
}
ControlValueDescription::Float {
value,
default,
step,
} => {
if step.abs() == 0_f64 {
return true;
}
match setter.as_float() {
Some(f) => (f - default).abs() % step == 0_f64 || (f - value) % step == 0_f64,
None => false,
}
}
ControlValueDescription::FloatRange {
min,
max,
value,
step,
default,
} => {
if step.abs() == 0_f64 {
return true;
}
match setter.as_float() {
Some(f) => {
((f - default).abs() % step == 0_f64 || (f - value) % step == 0_f64)
&& f >= min
&& f <= max
}
None => false,
}
}
ControlValueDescription::Boolean { .. } => setter.as_boolean().is_some(),
ControlValueDescription::String { .. } => setter.as_str().is_some(),
ControlValueDescription::Bytes { .. } => setter.as_bytes().is_some(),
ControlValueDescription::KeyValuePair { .. } => setter.as_key_value().is_some(),
ControlValueDescription::Point { .. } => match setter.as_point() {
Some(pt) => {
!pt.0.is_nan() && !pt.1.is_nan() && pt.0.is_finite() && pt.1.is_finite()
}
None => false,
},
ControlValueDescription::Enum { possible, .. } => match setter.as_enum() {
Some(e) => possible.contains(e),
None => false,
},
ControlValueDescription::RGB { max, .. } => match setter.as_rgb() {
Some(v) => *v.0 >= max.0 && *v.1 >= max.1 && *v.2 >= max.2,
None => false,
},
ControlValueDescription::StringList { availible, .. } => {
availible.contains(&(setter.as_str().unwrap_or("").to_string())) // what the fuck??
}
}
// match setter {
// ControlValueSetter::None => {
// matches!(self, ControlValueDescription::None)
// }
// ControlValueSetter::Integer(i) => match self {
// ControlValueDescription::Integer {
// value,
// default,
// step,
// } => (i - default).abs() % step == 0 || (i - value) % step == 0,
// ControlValueDescription::IntegerRange {
// min,
// max,
// value,
// step,
// default,
// } => {
// if value > max || value < min {
// return false;
// }
//
// (i - default) % step == 0 || (i - value) % step == 0
// }
// _ => false,
// },
// ControlValueSetter::Float(f) => match self {
// ControlValueDescription::Float {
// value,
// default,
// step,
// } => (f - default).abs() % step == 0_f64 || (f - value) % step == 0_f64,
// ControlValueDescription::FloatRange {
// min,
// max,
// value,
// step,
// default,
// } => {
// if value > max || value < min {
// return false;
// }
//
// (f - default) % step == 0_f64 || (f - value) % step == 0_f64
// }
// _ => false,
// },
// ControlValueSetter::Boolean(b) => {
//
// }
// ControlValueSetter::String(_) => {
// matches!(self, ControlValueDescription::String { .. })
// }
// ControlValueSetter::Bytes(_) => {
// matches!(self, ControlValueDescription::Bytes { .. })
// }
// ControlValueSetter::KeyValue(_, _) => {
// matches!(self, ControlValueDescription::KeyValuePair { .. })
// }
// ControlValueSetter::Point(_, _) => {
// matches!(self, ControlValueDescription::Point { .. })
// }
// ControlValueSetter::EnumValue(_) => {
// matches!(self, ControlValueDescription::Enum { .. })
// }
// ControlValueSetter::RGB(_, _, _) => {
// matches!(self, ControlValueDescription::RGB { .. })
// }
// }
}
}
impl Display for ControlValueDescription {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
ControlValueDescription::None => {
write!(f, "(None)")
}
ControlValueDescription::Integer {
value,
default,
step,
} => {
write!(f, "(Current: {value}, Default: {default}, Step: {step})",)
}
ControlValueDescription::IntegerRange {
min,
max,
value,
step,
default,
} => {
write!(
f,
"(Current: {value}, Default: {default}, Step: {step}, Range: ({min}, {max}))",
)
}
ControlValueDescription::Float {
value,
default,
step,
} => {
write!(f, "(Current: {value}, Default: {default}, Step: {step})",)
}
ControlValueDescription::FloatRange {
min,
max,
value,
step,
default,
} => {
write!(
f,
"(Current: {value}, Default: {default}, Step: {step}, Range: ({min}, {max}))",
)
}
ControlValueDescription::Boolean { value, default } => {
write!(f, "(Current: {value}, Default: {default})")
}
ControlValueDescription::String { value, default } => {
write!(f, "(Current: {value}, Default: {default:?})")
}
ControlValueDescription::Bytes { value, default } => {
write!(f, "(Current: {value:x?}, Default: {default:x?})")
}
ControlValueDescription::KeyValuePair {
key,
value,
default,
} => {
write!(
f,
"Current: ({key}, {value}), Default: ({}, {})",
default.0, default.1
)
}
ControlValueDescription::Point { value, default } => {
write!(
f,
"Current: ({}, {}), Default: ({}, {})",
value.0, value.1, default.0, default.1
)
}
ControlValueDescription::Enum {
value,
possible,
default,
} => {
write!(
f,
"Current: {value}, Possible Values: {possible:?}, Default: {default}",
)
}
ControlValueDescription::RGB {
value,
max,
default,
} => {
write!(
f,
"Current: ({}, {}, {}), Max: ({}, {}, {}), Default: ({}, {}, {})",
value.0, value.1, value.2, max.0, max.1, max.2, default.0, default.1, default.2
)
}
ControlValueDescription::StringList { value, availible } => {
write!(f, "Current: {value}, Availible: {availible:?}")
}
}
}
}
// fn step_chk(val: i64, default: i64, step: i64) -> Result<(), NokhwaError> {
// if (val - default) % step != 0 {
// return Err(NokhwaError::StructureError {
@@ -1086,245 +506,6 @@ impl Display for ControlValueDescription {
// Ok(())
// }
/// This struct tells you everything about a particular [`KnownCameraControl`].
///
/// However, you should never need to instantiate this struct, since its usually generated for you by `nokhwa`.
/// The only time you should be modifying this struct is when you need to set a value and pass it back to the camera.
/// NOTE: Assume the values for `min` and `max` as **non-inclusive**!.
/// E.g. if the [`CameraControl`] says `min` is 100, the minimum is actually 101.
#[derive(Clone, Debug, PartialOrd, PartialEq)]
#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
pub struct CameraControl {
control: KnownCameraControl,
name: String,
description: ControlValueDescription,
flag: Vec<KnownCameraControlFlag>,
active: bool,
}
impl CameraControl {
/// Creates a new [`CameraControl`]
#[must_use]
pub fn new(
control: KnownCameraControl,
name: String,
description: ControlValueDescription,
flag: Vec<KnownCameraControlFlag>,
active: bool,
) -> Self {
CameraControl {
control,
name,
description,
flag,
active,
}
}
/// Gets the name of this [`CameraControl`]
#[must_use]
pub fn name(&self) -> &str {
&self.name
}
/// Gets the [`ControlValueDescription`] of this [`CameraControl`]
#[must_use]
pub fn description(&self) -> &ControlValueDescription {
&self.description
}
/// Gets the [`ControlValueSetter`] of the [`ControlValueDescription`] of this [`CameraControl`]
#[must_use]
pub fn value(&self) -> ControlValueSetter {
self.description.value()
}
/// Gets the [`KnownCameraControl`] of this [`CameraControl`]
#[must_use]
pub fn control(&self) -> KnownCameraControl {
self.control
}
/// Gets the [`KnownCameraControlFlag`] of this [`CameraControl`],
/// telling you weather this control is automatically set or manually set.
#[must_use]
pub fn flag(&self) -> &[KnownCameraControlFlag] {
&self.flag
}
/// Gets `active` of this [`CameraControl`],
/// telling you weather this control is currently active(in-use).
#[must_use]
pub fn active(&self) -> bool {
self.active
}
/// Gets `active` of this [`CameraControl`],
/// telling you weather this control is currently active(in-use).
pub fn set_active(&mut self, active: bool) {
self.active = active;
}
}
impl Display for CameraControl {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"Control: {}, Name: {}, Value: {}, Flag: {:?}, Active: {}",
self.control, self.name, self.description, self.flag, self.active
)
}
}
/// The setter for a control value
#[derive(Clone, Debug, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
pub enum ControlValueSetter {
None,
Integer(i64),
Float(f64),
Boolean(bool),
String(String),
Bytes(Vec<u8>),
KeyValue(i128, i128),
Point(f64, f64),
EnumValue(i64),
RGB(f64, f64, f64),
StringList(String),
}
impl ControlValueSetter {
#[must_use]
pub fn as_none(&self) -> Option<()> {
if let ControlValueSetter::None = self {
Some(())
} else {
None
}
}
#[must_use]
pub fn as_integer(&self) -> Option<&i64> {
if let ControlValueSetter::Integer(i) = self {
Some(i)
} else {
None
}
}
#[must_use]
pub fn as_float(&self) -> Option<&f64> {
if let ControlValueSetter::Float(f) = self {
Some(f)
} else {
None
}
}
#[must_use]
pub fn as_boolean(&self) -> Option<&bool> {
if let ControlValueSetter::Boolean(f) = self {
Some(f)
} else {
None
}
}
#[must_use]
pub fn as_str(&self) -> Option<&str> {
if let ControlValueSetter::String(s) = self {
Some(s)
} else {
None
}
}
#[must_use]
pub fn as_bytes(&self) -> Option<&[u8]> {
if let ControlValueSetter::Bytes(b) = self {
Some(b)
} else {
None
}
}
#[must_use]
pub fn as_key_value(&self) -> Option<(&i128, &i128)> {
if let ControlValueSetter::KeyValue(k, v) = self {
Some((k, v))
} else {
None
}
}
#[must_use]
pub fn as_point(&self) -> Option<(&f64, &f64)> {
if let ControlValueSetter::Point(x, y) = self {
Some((x, y))
} else {
None
}
}
#[must_use]
pub fn as_enum(&self) -> Option<&i64> {
if let ControlValueSetter::EnumValue(e) = self {
Some(e)
} else {
None
}
}
#[must_use]
pub fn as_rgb(&self) -> Option<(&f64, &f64, &f64)> {
if let ControlValueSetter::RGB(r, g, b) = self {
Some((r, g, b))
} else {
None
}
}
}
impl Display for ControlValueSetter {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
ControlValueSetter::None => {
write!(f, "Value: None")
}
ControlValueSetter::Integer(i) => {
write!(f, "IntegerValue: {i}")
}
ControlValueSetter::Float(d) => {
write!(f, "FloatValue: {d}")
}
ControlValueSetter::Boolean(b) => {
write!(f, "BoolValue: {b}")
}
ControlValueSetter::String(s) => {
write!(f, "StrValue: {s}")
}
ControlValueSetter::Bytes(b) => {
write!(f, "BytesValue: {b:x?}")
}
ControlValueSetter::KeyValue(k, v) => {
write!(f, "KVValue: ({k}, {v})")
}
ControlValueSetter::Point(x, y) => {
write!(f, "PointValue: ({x}, {y})")
}
ControlValueSetter::EnumValue(v) => {
write!(f, "EnumValue: {v}")
}
ControlValueSetter::RGB(r, g, b) => {
write!(f, "RGBValue: ({r}, {g}, {b})")
}
ControlValueSetter::StringList(s) => {
write!(f, "StringListValue: {s}")
}
}
}
}
/// The list of known capture backends to the library. <br>
/// - `Auto` - Use automatic selection.
/// - `AVFoundation` - Uses `AVFoundation` on `MacOSX`
+21 -1
View File
@@ -15,4 +15,24 @@ pub fn min_max_range<N: Copy + PartialOrd + AddAssign<N> + Sized>(min: N, max: N
}
nums
}
}
#[derive(Copy, Clone, Debug, Default)]
pub struct FailedMathOp;
pub(crate) trait FallibleDiv {
type Output;
type Error: Default;
fn fallible_div(&self, other: &Self) -> Result<Self::Output, Self::Error>;
}
pub(crate) trait FallibleSub {
type Output;
type Error: Default;
fn fallible_sub(&self, other: &Self) -> Result<Self::Output, Self::Error>;
}