From 9c357abf1a9ab478a1c4262b6480b007ba26b0eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Wed, 12 Jul 2017 13:25:11 +0300 Subject: [PATCH] Add support for Fractions --- Cargo.lock | 26 +++++ gstreamer/Cargo.toml | 1 + gstreamer/src/caps.rs | 9 +- gstreamer/src/lib.rs | 5 + gstreamer/src/message.rs | 5 +- gstreamer/src/value.rs | 218 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 259 insertions(+), 5 deletions(-) create mode 100644 gstreamer/src/value.rs diff --git a/Cargo.lock b/Cargo.lock index 8fa2ff01d..4cd24152b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,6 +8,7 @@ dependencies = [ "gobject-sys 0.3.4 (git+https://github.com/gtk-rs/sys)", "gstreamer-sys 0.1.1 (git+https://github.com/sdroege/gstreamer-sys)", "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", + "num-rational 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -78,6 +79,28 @@ name = "libc" version = "0.2.26" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "num-integer" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-traits 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-rational" +version = "0.1.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-integer 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-traits" +version = "0.1.39" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "pkg-config" version = "0.3.9" @@ -91,4 +114,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum gstreamer-sys 0.1.1 (git+https://github.com/sdroege/gstreamer-sys)" = "" "checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf" "checksum libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)" = "30885bcb161cf67054244d10d4a7f4835ffd58773bc72e07d35fecf472295503" +"checksum num-integer 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)" = "ef1a4bf6f9174aa5783a9b4cc892cacd11aebad6c69ad027a0b65c6ca5f8aa37" +"checksum num-rational 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)" = "33c881e104a26e1accc09449374c095ff2312c8e0c27fab7bbefe16eac7c776d" +"checksum num-traits 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "1708c0628602a98b52fad936cf3edb9a107af06e52e49fdf0707e884456a6af6" "checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903" diff --git a/gstreamer/Cargo.toml b/gstreamer/Cargo.toml index 14ea1264c..d16f712d8 100644 --- a/gstreamer/Cargo.toml +++ b/gstreamer/Cargo.toml @@ -10,6 +10,7 @@ glib-sys = { version = "0.3.4", git = "https://github.com/gtk-rs/sys" } gobject-sys = { version = "0.3.4", git = "https://github.com/gtk-rs/sys" } gstreamer-sys = { version = "0.1.1", git = "https://github.com/sdroege/gstreamer-sys", features = ["v1_8"] } glib = { version = "0.1.3", git = "https://github.com/gtk-rs/glib" } +num-rational = { version = "0.1.38", default-features = false, features = [] } [features] v1_10 = ["gstreamer-sys/v1_10", "v1_8"] diff --git a/gstreamer/src/caps.rs b/gstreamer/src/caps.rs index cecae34f8..e33e09d7f 100644 --- a/gstreamer/src/caps.rs +++ b/gstreamer/src/caps.rs @@ -225,6 +225,7 @@ unsafe impl Send for CapsRef {} mod tests { use super::*; use glib::ToValue; + use Fraction; #[test] fn test_simple() { @@ -236,15 +237,15 @@ mod tests { ("int", &12.to_value()), ("bool", &true.to_value()), ("string", &"bla".to_value()), - //("fraction", (1, 2).into()), + ("fraction", &Fraction::new(1, 2).to_value()), //("array", vec![1.into(), 2.into()].into()), ], ); assert_eq!( caps.to_string(), - "foo/bar, int=(int)12, bool=(boolean)true, string=(string)bla" + "foo/bar, int=(int)12, bool=(boolean)true, string=(string)bla, fraction=(fraction)1/2" ); //, \ - // fraction=(fraction)1/2, array=(int)< 1, 2 >" + // array=(int)< 1, 2 >" //); let s = caps.get_structure(0).unwrap(); @@ -256,7 +257,7 @@ mod tests { ("int", &12.to_value()), ("bool", &true.to_value()), ("string", &"bla".to_value()), - //("fraction", (1, 2).into()), + ("fraction", &Fraction::new(1, 2).to_value()), //("array", vec![1.into(), 2.into()].into()), ], ).as_ref() diff --git a/gstreamer/src/lib.rs b/gstreamer/src/lib.rs index b9a0cd395..8d0ad7aae 100644 --- a/gstreamer/src/lib.rs +++ b/gstreamer/src/lib.rs @@ -17,6 +17,8 @@ extern crate gstreamer_sys as ffi; #[macro_use] extern crate glib; +extern crate num_rational; + use glib::translate::{from_glib, from_glib_full}; macro_rules! callback_guard { @@ -60,6 +62,9 @@ mod bin; mod bus; pub use bin::BinExtManual; +mod value; +pub use value::*; + use std::ptr; pub fn init() -> Result<(), glib::Error> { diff --git a/gstreamer/src/message.rs b/gstreamer/src/message.rs index e864705bf..4138e96c9 100644 --- a/gstreamer/src/message.rs +++ b/gstreamer/src/message.rs @@ -1951,7 +1951,10 @@ impl<'a> RedirectBuilder<'a> { } } - pub fn entries(self, entries: &'a [(&'a str, Option<&'a TagList>, Option<&'a Structure>)]) -> Self { + pub fn entries( + self, + entries: &'a [(&'a str, Option<&'a TagList>, Option<&'a Structure>)], + ) -> Self { Self { entries: Some(entries), ..self diff --git a/gstreamer/src/value.rs b/gstreamer/src/value.rs new file mode 100644 index 000000000..4391f4140 --- /dev/null +++ b/gstreamer/src/value.rs @@ -0,0 +1,218 @@ +// Copyright (C) 2017 Sebastian Dröge +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use num_rational::Rational32; +use std::fmt; +use std::ops; +use std::mem; + +use glib; +use glib::value::{Value, FromValue, FromValueOptional, ToValue, SetValue, SetValueOptional}; +use glib::translate::{from_glib, ToGlibPtr, ToGlibPtrMut}; + +use ffi; +use gobject_ffi; + +#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash)] +pub struct Fraction(pub Rational32); + +impl Fraction { + pub fn new(num: i32, den: i32) -> Fraction { + (num, den).into() + } + + pub fn approximate_f32(x: f32) -> Option { + Rational32::approximate_float(x).map(|r| r.into()) + } + + pub fn approximate_f64(x: f64) -> Option { + Rational32::approximate_float(x).map(|r| r.into()) + } +} + +impl fmt::Display for Fraction { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.0.fmt(f) + } +} + +impl ops::Deref for Fraction { + type Target = Rational32; + + fn deref(&self) -> &Rational32 { + &self.0 + } +} + +impl ops::DerefMut for Fraction { + fn deref_mut(&mut self) -> &mut Rational32 { + &mut self.0 + } +} + +impl AsRef for Fraction { + fn as_ref(&self) -> &Rational32 { + &self.0 + } +} + +impl ops::Mul for Fraction { + type Output = Fraction; + + fn mul(self, other: Fraction) -> Fraction { + Fraction(self.0.mul(other.0)) + } +} + +impl ops::Mul for Fraction { + type Output = Fraction; + + fn mul(self, other: i32) -> Fraction { + self.mul(Fraction::from(other)) + } +} + +impl ops::Div for Fraction { + type Output = Fraction; + + fn div(self, other: Fraction) -> Fraction { + Fraction(self.0.div(other.0)) + } +} + +impl ops::Div for Fraction { + type Output = Fraction; + + fn div(self, other: i32) -> Fraction { + self.div(Fraction::from(other)) + } +} + +impl ops::Add for Fraction { + type Output = Fraction; + + fn add(self, other: Fraction) -> Fraction { + Fraction(self.0.add(other.0)) + } +} + +impl ops::Add for Fraction { + type Output = Fraction; + + fn add(self, other: i32) -> Fraction { + self.add(Fraction::from(other)) + } +} + +impl ops::Sub for Fraction { + type Output = Fraction; + + fn sub(self, other: Fraction) -> Fraction { + Fraction(self.0.sub(other.0)) + } +} + +impl ops::Sub for Fraction { + type Output = Fraction; + + fn sub(self, other: i32) -> Fraction { + self.sub(Fraction::from(other)) + } +} + +impl ops::Rem for Fraction { + type Output = Fraction; + + fn rem(self, other: Fraction) -> Fraction { + Fraction(self.0.rem(other.0)) + } +} + +impl ops::Rem for Fraction { + type Output = Fraction; + + fn rem(self, other: i32) -> Fraction { + self.rem(Fraction::from(other)) + } +} + +impl ops::Neg for Fraction { + type Output = Fraction; + + fn neg(self) -> Fraction { + Fraction(self.0.neg()) + } +} + +impl From for Fraction { + fn from(x: i32) -> Fraction { + Fraction(x.into()) + } +} + +impl From<(i32, i32)> for Fraction { + fn from(x: (i32, i32)) -> Fraction { + Fraction(x.into()) + } +} + +impl Into<(i32, i32)> for Fraction { + fn into(self) -> (i32, i32) { + self.0.into() + } +} + +impl From for Fraction { + fn from(x: Rational32) -> Fraction { + Fraction(x) + } +} + +impl From for Rational32 { + fn from(x: Fraction) -> Rational32 { + x.0 + } +} + +impl glib::types::StaticType for Fraction { + fn static_type() -> glib::types::Type { + unsafe { from_glib(ffi::gst_fraction_get_type()) } + } +} + +impl<'a> FromValue<'a> for Fraction { + unsafe fn from_value(v: &'a Value) -> Fraction { + let n = ffi::gst_value_get_fraction_numerator(v.to_glib_none().0); + let d = ffi::gst_value_get_fraction_denominator(v.to_glib_none().0); + + Fraction::new(n, d) + } +} + +impl<'a> FromValueOptional<'a> for Fraction { + unsafe fn from_value_optional(v: &'a Value) -> Option { + Some(Fraction::from_value(v)) + } +} + +impl SetValue for Fraction { + unsafe fn set_value(v: &mut Value, f: &Self) { + ffi::gst_value_set_fraction(v.to_glib_none_mut().0, *f.numer(), *f.denom()); + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_simple() { + let f: Fraction = (1, 2).into(); + println!("{}", f * 2); + } +}