forked from mirrors/gstreamer-rs
format/specific: don't expose inner as pub
... users would be able to bypass the range checks and build a defined Rust value which would be interpreted as `None` in C code. Added format module examples for formatted values constructions.
This commit is contained in:
parent
f6336b1be3
commit
08551bb1bc
9 changed files with 142 additions and 60 deletions
|
@ -294,20 +294,19 @@ mod tests {
|
|||
|
||||
let mut buffer = gst::Buffer::with_size(1024).unwrap();
|
||||
|
||||
let start = gst::format::Default::ONE;
|
||||
let stop = 2 * gst::format::Default::ONE;
|
||||
|
||||
{
|
||||
let cmeta = AudioClippingMeta::add(
|
||||
buffer.get_mut().unwrap(),
|
||||
gst::format::Default(1),
|
||||
gst::format::Default(2),
|
||||
);
|
||||
assert_eq!(cmeta.start().try_into(), Ok(Some(gst::format::Default(1))));
|
||||
assert_eq!(cmeta.end().try_into(), Ok(Some(gst::format::Default(2))));
|
||||
let cmeta = AudioClippingMeta::add(buffer.get_mut().unwrap(), start, stop);
|
||||
assert_eq!(cmeta.start().try_into(), Ok(Some(start)));
|
||||
assert_eq!(cmeta.end().try_into(), Ok(Some(stop)));
|
||||
}
|
||||
|
||||
{
|
||||
let cmeta = buffer.meta::<AudioClippingMeta>().unwrap();
|
||||
assert_eq!(cmeta.start().try_into(), Ok(Some(gst::format::Default(1))));
|
||||
assert_eq!(cmeta.end().try_into(), Ok(Some(gst::format::Default(2))));
|
||||
assert_eq!(cmeta.start().try_into(), Ok(Some(start)));
|
||||
assert_eq!(cmeta.end().try_into(), Ok(Some(stop)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ use super::{
|
|||
};
|
||||
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Default)]
|
||||
pub struct ClockTime(pub(crate) u64);
|
||||
pub struct ClockTime(u64);
|
||||
|
||||
impl ClockTime {
|
||||
#[doc(alias = "GST_SECOND")]
|
||||
|
|
|
@ -7,14 +7,20 @@ use crate::ClockTime;
|
|||
|
||||
impl Serialize for ClockTime {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
self.0.serialize(serializer)
|
||||
use std::ops::Deref;
|
||||
self.deref().serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for ClockTime {
|
||||
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
||||
skip_assert_initialized!();
|
||||
u64::deserialize(deserializer).map(ClockTime::from_nseconds)
|
||||
u64::deserialize(deserializer).and_then(|value| {
|
||||
ClockTime::try_from(value).map_err(|_| {
|
||||
use serde::de::{Error, Unexpected};
|
||||
D::Error::invalid_value(Unexpected::Unsigned(value), &"valid `ClockTime`")
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -75,7 +75,7 @@ mod tests {
|
|||
let res = serde_json::to_string(&value).unwrap();
|
||||
assert_eq!("{\"Undefined\":42}".to_owned(), res);
|
||||
|
||||
let value = GenericFormattedValue::from(Default(42));
|
||||
let value = GenericFormattedValue::from(42 * Default::ONE);
|
||||
let res = ron::ser::to_string_pretty(&value, pretty_config.clone());
|
||||
assert_eq!(Ok("Default(Some(42))".to_owned()), res);
|
||||
let res = serde_json::to_string(&value).unwrap();
|
||||
|
@ -87,7 +87,7 @@ mod tests {
|
|||
let res = serde_json::to_string(&value).unwrap();
|
||||
assert_eq!("{\"Default\":null}".to_owned(), res);
|
||||
|
||||
let value = GenericFormattedValue::from(Bytes(42));
|
||||
let value = GenericFormattedValue::from(42 * Bytes::ONE);
|
||||
let res = ron::ser::to_string_pretty(&value, pretty_config.clone());
|
||||
assert_eq!(Ok("Bytes(Some(42))".to_owned()), res);
|
||||
let res = serde_json::to_string(&value).unwrap();
|
||||
|
@ -99,19 +99,21 @@ mod tests {
|
|||
let res = serde_json::to_string(&value).unwrap();
|
||||
assert_eq!("{\"Time\":42123456789}".to_owned(), res);
|
||||
|
||||
let value = GenericFormattedValue::from(Buffers(42));
|
||||
let value = GenericFormattedValue::from(42 * Buffers::ONE);
|
||||
let res = ron::ser::to_string_pretty(&value, pretty_config.clone());
|
||||
assert_eq!(Ok("Buffers(Some(42))".to_owned()), res);
|
||||
let res = serde_json::to_string(&value).unwrap();
|
||||
assert_eq!("{\"Buffers\":42}".to_owned(), res);
|
||||
|
||||
let value = GenericFormattedValue::from(Percent::try_from(0.42).unwrap());
|
||||
let percent = Percent::try_from(0.42).unwrap();
|
||||
let value = GenericFormattedValue::from(percent);
|
||||
let res = ron::ser::to_string_pretty(&value, pretty_config.clone());
|
||||
assert_eq!(Ok("Percent(Some(4200))".to_owned()), res);
|
||||
let res = serde_json::to_string(&value).unwrap();
|
||||
assert_eq!("{\"Percent\":4200}".to_owned(), res);
|
||||
|
||||
let value = GenericFormattedValue::Other(Format::Percent, Other::try_from(42).ok());
|
||||
let other = Other::try_from(42).ok();
|
||||
let value = GenericFormattedValue::Other(Format::Percent, other);
|
||||
let res = ron::ser::to_string_pretty(&value, pretty_config.clone());
|
||||
assert_eq!(Ok("Other(Percent, Some(42))".to_owned()), res);
|
||||
let res = serde_json::to_string(&value).unwrap();
|
||||
|
@ -130,14 +132,14 @@ mod tests {
|
|||
|
||||
let value_ron = "Default(Some(42))";
|
||||
let value_de: GenericFormattedValue = ron::de::from_str(value_ron).unwrap();
|
||||
assert_eq!(value_de, GenericFormattedValue::from(Default(42)));
|
||||
assert_eq!(value_de, GenericFormattedValue::from(42 * Default::ONE));
|
||||
|
||||
let value_json = "{\"Default\":42}";
|
||||
let value_de: GenericFormattedValue = serde_json::from_str(value_json).unwrap();
|
||||
assert_eq!(value_de, GenericFormattedValue::from(Default(42)));
|
||||
assert_eq!(value_de, GenericFormattedValue::from(42 * Default::ONE));
|
||||
|
||||
let value_ron = "Other(Percent, Some(42))";
|
||||
let gfv_value = GenericFormattedValue::Other(Format::Percent, Other::try_from(42).ok());
|
||||
let gfv_value = GenericFormattedValue::Other(Format::Percent, Some(42 * Other::ONE));
|
||||
|
||||
let value_de: GenericFormattedValue = ron::de::from_str(value_ron).unwrap();
|
||||
assert_eq!(value_de, gfv_value);
|
||||
|
@ -159,16 +161,14 @@ mod tests {
|
|||
}
|
||||
);
|
||||
|
||||
test_roundrip!(GenericFormattedValue::Undefined(Undefined::from(42)));
|
||||
test_roundrip!(GenericFormattedValue::from(Default(42)));
|
||||
test_roundrip!(GenericFormattedValue::from(Bytes(42)));
|
||||
test_roundrip!(GenericFormattedValue::Undefined(Undefined(42)));
|
||||
test_roundrip!(GenericFormattedValue::from(42 * Default::ONE));
|
||||
test_roundrip!(GenericFormattedValue::from(42 * Bytes::ONE));
|
||||
test_roundrip!(GenericFormattedValue::from(ClockTime::from_nseconds(
|
||||
42_123_456_789
|
||||
)));
|
||||
test_roundrip!(GenericFormattedValue::from(Buffers(42)));
|
||||
test_roundrip!(GenericFormattedValue::from(
|
||||
Percent::try_from(0.42).unwrap()
|
||||
));
|
||||
test_roundrip!(GenericFormattedValue::from(42 * Buffers::ONE));
|
||||
test_roundrip!(GenericFormattedValue::from(42 * Percent::ONE));
|
||||
let gfv_value = GenericFormattedValue::Other(Format::Percent, Other::try_from(42).ok());
|
||||
test_roundrip!(gfv_value);
|
||||
test_roundrip!(GenericFormattedValue::new(Format::__Unknown(7), 42));
|
||||
|
|
|
@ -229,9 +229,16 @@ macro_rules! impl_unsigned_int_into_signed(
|
|||
|
||||
macro_rules! impl_common_ops_for_newtype_uint(
|
||||
($typ:ty, $inner:ty) => {
|
||||
impl_common_ops_for_newtype_uint!($typ, $inner, one: 1);
|
||||
};
|
||||
|
||||
($typ:ty, $inner:ty, one: $one:expr$(,)?) => {
|
||||
impl $typ {
|
||||
pub const ZERO: Self = Self(0);
|
||||
pub const NONE: Option<Self> = None;
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// The unitary value.
|
||||
pub const ONE: Self = Self($one);
|
||||
|
||||
pub const MAX_SIGNED: crate::Signed::<$typ> = crate::Signed::Positive(Self::MAX);
|
||||
pub const MIN_SIGNED: crate::Signed::<$typ> = crate::Signed::Negative(Self::MAX);
|
||||
|
@ -1501,22 +1508,30 @@ macro_rules! impl_format_value_traits(
|
|||
);
|
||||
|
||||
macro_rules! option_glib_newtype_from_to {
|
||||
($typ_:ident, $none_value:expr) => {
|
||||
($typ:ident, $none_value:expr) => {
|
||||
#[doc(hidden)]
|
||||
impl IntoGlib for $typ_ {
|
||||
impl IntoGlib for $typ {
|
||||
type GlibType = u64;
|
||||
fn into_glib(self) -> u64 {
|
||||
assert_ne!(
|
||||
self.0, $none_value,
|
||||
concat!(
|
||||
"attempt to build a `None` glib variant",
|
||||
"from a non-`Option` type ",
|
||||
stringify!($typ),
|
||||
),
|
||||
);
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
impl OptionIntoGlib for $typ_ {
|
||||
impl OptionIntoGlib for $typ {
|
||||
const GLIB_NONE: u64 = $none_value;
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
impl TryFromGlib<u64> for $typ_ {
|
||||
impl TryFromGlib<u64> for $typ {
|
||||
type Error = GlibNoneError;
|
||||
#[inline]
|
||||
unsafe fn try_from_glib(val: u64) -> Result<Self, GlibNoneError> {
|
||||
|
@ -1525,7 +1540,7 @@ macro_rules! option_glib_newtype_from_to {
|
|||
return Err(GlibNoneError);
|
||||
}
|
||||
|
||||
Ok($typ_(val))
|
||||
Ok($typ(val))
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -17,7 +17,8 @@
|
|||
//! Specific formatted values are also guaranteed to always represent a valid value.
|
||||
//! For instance:
|
||||
//!
|
||||
//! - [`Percent`] only allows values in the range [0, 1_000_000].
|
||||
//! - [`Percent`] only allows values in the integer range [0, 1_000_000] or
|
||||
//! float range [0.0, 1.0].
|
||||
//! - [`ClockTime`] can use all `u64` values except `u64::MAX` which is reserved by
|
||||
//! the C constant `GST_CLOCK_TIME_NONE`.
|
||||
//!
|
||||
|
@ -60,6 +61,52 @@
|
|||
//! assert_eq!(start.format(), gst::Format::Time);
|
||||
//! ```
|
||||
//!
|
||||
//! ### Building a specific formatted value
|
||||
//!
|
||||
//! ```
|
||||
//! # use gstreamer as gst;
|
||||
//! use gst::format::{Buffers, Bytes, ClockTime, Default, Percent};
|
||||
//!
|
||||
//! // Specific formatted values implement the faillible `try_from` constructor:
|
||||
//! let default = Default::try_from(42).unwrap();
|
||||
//! assert_eq!(*default, 42);
|
||||
//! assert_eq!(Default::try_from(42), Ok(default));
|
||||
//! assert_eq!(Default::try_from(42).ok(), Some(default));
|
||||
//!
|
||||
//! // `ClockTime` provides specific constructors:
|
||||
//! let time = ClockTime::from_nseconds(45_834_908_569_837);
|
||||
//! let time = ClockTime::from_seconds(20);
|
||||
//!
|
||||
//! // This can be convenient:
|
||||
//! assert_eq!(
|
||||
//! 20 * ClockTime::MSECOND,
|
||||
//! ClockTime::from_nseconds(20_000_000),
|
||||
//! );
|
||||
//! assert_eq!(
|
||||
//! 40 * ClockTime::SECOND,
|
||||
//! ClockTime::from_nseconds(40_000_000_000),
|
||||
//! );
|
||||
//!
|
||||
//! // Specific formatted values provide the `ONE` value:
|
||||
//! assert_eq!(*(128 * Buffers::ONE), 128);
|
||||
//!
|
||||
//! // `ZERO` and `NONE` can also come in handy sometimes:
|
||||
//! assert_eq!(*Buffers::ZERO, 0);
|
||||
//! assert!(ClockTime::NONE.is_none());
|
||||
//!
|
||||
//! // `Bytes` also comes with usual multipliers:
|
||||
//! assert_eq!(*(512 * Bytes::K), 512 * 1024);
|
||||
//! assert_eq!(*(8 * Bytes::M), 8 * 1024 * 1024);
|
||||
//! assert_eq!(*(4 * Bytes::G), 4 * 1024 * 1024 * 1024);
|
||||
//!
|
||||
//! // `Percent` can be built from a float:
|
||||
//! let a_quarter = Percent::try_from(0.25).unwrap();
|
||||
//! // `Percent` has `SCALE` which represents 100%:
|
||||
//! assert_eq!(Percent::SCALE / 4, a_quarter);
|
||||
//! // ... and `ONE` which is 1%:
|
||||
//! assert_eq!(25 * Percent::ONE, a_quarter);
|
||||
//! ```
|
||||
//!
|
||||
//! ### Displaying a formatted value
|
||||
//!
|
||||
//! Formatted values implement the [`Display`] trait which allows getting
|
||||
|
@ -334,7 +381,7 @@
|
|||
//! // Signed formatted values implement the `MulDiv` trait:
|
||||
//! # use gst::prelude::MulDiv;
|
||||
//! # let rate = 48000u64;
|
||||
//! let samples = gst::format::Default(1024).into_negative();
|
||||
//! let samples = (1024 * gst::format::Default::ONE).into_negative();
|
||||
//! let duration = samples
|
||||
//! .mul_div_round(*gst::ClockTime::SECOND, rate)
|
||||
//! .map(|signed_default| {
|
||||
|
@ -383,7 +430,7 @@
|
|||
//! # use gstreamer as gst;
|
||||
//! # use gst::prelude::{Displayable, ElementExtManual};
|
||||
//! # gst::init();
|
||||
//! # let event = gst::event::SegmentDone::new(gst::format::Buffers(512));
|
||||
//! # let event = gst::event::SegmentDone::new(512 * gst::format::Buffers::ONE);
|
||||
//! if let gst::EventView::SegmentDone(seg_done_evt) = event.view() {
|
||||
//! use gst::GenericFormattedValue::*;
|
||||
//! match seg_done_evt.get() {
|
||||
|
@ -592,11 +639,11 @@ mod tests {
|
|||
fn incompatible() {
|
||||
with_compatible_formats(
|
||||
ClockTime::ZERO,
|
||||
GenericFormattedValue::Buffers(Some(Buffers(42))),
|
||||
GenericFormattedValue::Buffers(Some(42 * Buffers::ONE)),
|
||||
)
|
||||
.unwrap_err();
|
||||
with_compatible_formats(
|
||||
GenericFormattedValue::Buffers(Some(Buffers(42))),
|
||||
GenericFormattedValue::Buffers(Some(42 * Buffers::ONE)),
|
||||
ClockTime::NONE,
|
||||
)
|
||||
.unwrap_err();
|
||||
|
@ -744,20 +791,18 @@ mod tests {
|
|||
assert!(signed.positive().is_none());
|
||||
assert_eq!(signed.signum(), -1);
|
||||
|
||||
let def = Default(1);
|
||||
|
||||
let signed = def.into_positive();
|
||||
assert_eq!(signed, Signed::Positive(def));
|
||||
let signed = Default::ONE.into_positive();
|
||||
assert_eq!(signed, Signed::Positive(Default::ONE));
|
||||
assert!(signed.is_positive());
|
||||
assert_eq!(signed.positive(), Some(def));
|
||||
assert_eq!(signed.positive(), Some(Default::ONE));
|
||||
assert!(!signed.is_negative());
|
||||
assert!(signed.negative().is_none());
|
||||
assert_eq!(signed.signum(), 1);
|
||||
|
||||
let signed = def.into_negative();
|
||||
assert_eq!(signed, Signed::Negative(def));
|
||||
let signed = Default::ONE.into_negative();
|
||||
assert_eq!(signed, Signed::Negative(Default::ONE));
|
||||
assert!(signed.is_negative());
|
||||
assert_eq!(signed.negative(), Some(def));
|
||||
assert_eq!(signed.negative(), Some(Default::ONE));
|
||||
assert!(!signed.is_positive());
|
||||
assert!(signed.positive().is_none());
|
||||
assert_eq!(signed.signum(), -1);
|
||||
|
@ -855,14 +900,14 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn display_new_types() {
|
||||
let bytes = Bytes(42);
|
||||
let bytes = 42 * Bytes::ONE;
|
||||
assert_eq!(&format!("{bytes}"), "42 bytes");
|
||||
assert_eq!(&format!("{}", bytes.display()), "42 bytes");
|
||||
|
||||
assert_eq!(&format!("{}", Some(bytes).display()), "42 bytes");
|
||||
assert_eq!(&format!("{}", Bytes::NONE.display()), "undef. bytes");
|
||||
|
||||
let gv_1 = GenericFormattedValue::Percent(Percent::try_from(0.42).ok());
|
||||
let gv_1 = GenericFormattedValue::Percent(Some(42 * Percent::ONE));
|
||||
assert_eq!(&format!("{gv_1}"), "42 %");
|
||||
assert_eq!(
|
||||
&format!("{}", GenericFormattedValue::Percent(None)),
|
||||
|
@ -890,24 +935,25 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn display_signed() {
|
||||
let p_bytes = Bytes(42).into_positive();
|
||||
let bytes_42 = 42 * Bytes::ONE;
|
||||
let p_bytes = bytes_42.into_positive();
|
||||
assert_eq!(&format!("{p_bytes}"), "+42 bytes");
|
||||
assert_eq!(&format!("{}", p_bytes.display()), "+42 bytes");
|
||||
|
||||
let some_p_bytes = Some(p_bytes);
|
||||
assert_eq!(&format!("{}", some_p_bytes.display()), "+42 bytes");
|
||||
|
||||
let p_some_bytes = Signed::Positive(Some(Bytes(42)));
|
||||
let p_some_bytes = Signed::Positive(Some(bytes_42));
|
||||
assert_eq!(&format!("{}", p_some_bytes.display()), "+42 bytes");
|
||||
|
||||
let n_bytes = Bytes(42).into_negative();
|
||||
let n_bytes = bytes_42.into_negative();
|
||||
assert_eq!(&format!("{n_bytes}"), "-42 bytes");
|
||||
assert_eq!(&format!("{}", n_bytes.display()), "-42 bytes");
|
||||
|
||||
let some_n_bytes = Some(n_bytes);
|
||||
assert_eq!(&format!("{}", some_n_bytes.display()), "-42 bytes");
|
||||
|
||||
let n_some_bytes = Signed::Negative(Some(Bytes(42)));
|
||||
let n_some_bytes = Signed::Negative(Some(bytes_42));
|
||||
assert_eq!(&format!("{}", n_some_bytes.display()), "-42 bytes");
|
||||
|
||||
let p_none_bytes = Signed::Positive(Bytes::NONE);
|
||||
|
|
|
@ -21,7 +21,7 @@ pub trait SpecificFormattedValueFullRange: FormattedValueFullRange {}
|
|||
pub trait SpecificFormattedValueIntrinsic: TryFromGlib<i64> + FormattedValueIntrinsic {}
|
||||
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Debug, Default)]
|
||||
pub struct Buffers(pub u64);
|
||||
pub struct Buffers(u64);
|
||||
impl Buffers {
|
||||
#[doc(alias = "GST_BUFFER_OFFSET_NONE")]
|
||||
pub const OFFSET_NONE: u64 = ffi::GST_BUFFER_OFFSET_NONE;
|
||||
|
@ -35,8 +35,17 @@ option_glib_newtype_from_to!(Buffers, Buffers::OFFSET_NONE);
|
|||
glib_newtype_display!(Buffers, DisplayableOptionBuffers, Format::Buffers);
|
||||
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Debug, Default)]
|
||||
pub struct Bytes(pub u64);
|
||||
pub struct Bytes(u64);
|
||||
impl Bytes {
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// 1K Bytes (1024).
|
||||
pub const K: Self = Self(1024);
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// 1M Bytes (1024 * 1024).
|
||||
pub const M: Self = Self(1024 * 1024);
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// 1G Bytes (1024 * 1024 * 1024).
|
||||
pub const G: Self = Self(1024 * 1024 * 1024);
|
||||
pub const MAX: Self = Self(u64::MAX - 1);
|
||||
}
|
||||
|
||||
|
@ -47,7 +56,7 @@ option_glib_newtype_from_to!(Bytes, u64::MAX);
|
|||
glib_newtype_display!(Bytes, DisplayableOptionBytes, Format::Bytes);
|
||||
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Debug, Default)]
|
||||
pub struct Default(pub u64);
|
||||
pub struct Default(u64);
|
||||
impl Default {
|
||||
pub const MAX: Self = Self(u64::MAX - 1);
|
||||
}
|
||||
|
@ -61,15 +70,19 @@ glib_newtype_display!(Default, DisplayableOptionDefault, Format::Default);
|
|||
pub type Time = super::ClockTime;
|
||||
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Debug, Default)]
|
||||
pub struct Percent(pub u32);
|
||||
pub struct Percent(u32);
|
||||
impl Percent {
|
||||
#[doc(alias = "GST_FORMAT_PERCENT_MAX")]
|
||||
pub const MAX: Self = Self(ffi::GST_FORMAT_PERCENT_MAX as u32);
|
||||
#[doc(alias = "GST_FORMAT_PERCENT_SCALE")]
|
||||
pub const SCALE: u32 = ffi::GST_FORMAT_PERCENT_SCALE as u32;
|
||||
pub const SCALE: Self = Self(ffi::GST_FORMAT_PERCENT_SCALE as u32);
|
||||
}
|
||||
|
||||
impl_common_ops_for_newtype_uint!(Percent, u32);
|
||||
impl_common_ops_for_newtype_uint!(
|
||||
Percent,
|
||||
u32,
|
||||
one: ffi::GST_FORMAT_PERCENT_SCALE as u32 / 100,
|
||||
);
|
||||
impl_signed_div_mul!(Percent, u32);
|
||||
|
||||
impl FormattedValue for Option<Percent> {
|
||||
|
@ -227,8 +240,7 @@ impl TryFrom<f32> for Percent {
|
|||
|
||||
impl std::fmt::Display for Percent {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
const ONE_PERCENT: f32 = Percent::SCALE as f32 / 100.0;
|
||||
std::fmt::Display::fmt(&(self.0 as f32 / ONE_PERCENT), f)?;
|
||||
std::fmt::Display::fmt(&(self.0 as f32 / (*Percent::ONE) as f32), f)?;
|
||||
f.write_str(" %")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,10 @@ use crate::Format;
|
|||
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Debug, Default)]
|
||||
pub struct Undefined(pub i64);
|
||||
|
||||
impl Undefined {
|
||||
pub const ONE: Undefined = Undefined(1);
|
||||
}
|
||||
|
||||
impl FormattedValue for Undefined {
|
||||
type FullRange = Undefined;
|
||||
|
||||
|
|
|
@ -173,7 +173,7 @@ USAGE: Choose one of the following options, then press enter:
|
|||
Command::NextFrame => {
|
||||
if let Some(video_sink) = pipeline.property::<Option<Element>>("video-sink") {
|
||||
// Send the event
|
||||
let step = Step::new(gst::format::Buffers(1), rate.abs(), true, false);
|
||||
let step = Step::new(gst::format::Buffers::ONE, rate.abs(), true, false);
|
||||
video_sink.send_event(step);
|
||||
println!("Stepping one frame\r");
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue