From ad03e1e5a1b9fea9d6ff22bba8b559f7d5c046c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Fri, 28 Jul 2017 14:52:35 +0100 Subject: [PATCH] Implement Int/Fraction ranges and Array/Lists for GstValue --- gstreamer/src/value.rs | 329 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 326 insertions(+), 3 deletions(-) diff --git a/gstreamer/src/value.rs b/gstreamer/src/value.rs index 9a49f0cf1..afd12c034 100644 --- a/gstreamer/src/value.rs +++ b/gstreamer/src/value.rs @@ -9,12 +9,15 @@ use num_rational::Rational32; use std::fmt; use std::ops; +use std::borrow::{Cow, Borrow}; +use std::slice; use glib; -use glib::value::{Value, FromValue, FromValueOptional, SetValue}; +use glib::value::{Value, FromValue, FromValueOptional, SetValue, ToValue}; use glib::translate::{from_glib, ToGlibPtr, ToGlibPtrMut}; use ffi; +use glib_ffi; #[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash)] pub struct Fraction(pub Rational32); @@ -204,5 +207,325 @@ impl SetValue for Fraction { } } -// TODO: Array, List, Ranges -// GStreamer value operations +#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] +pub struct IntRange { + min: T, + max: T, + step: T, +} + +impl IntRange { + pub fn min(&self) -> T { + self.min + } + + pub fn max(&self) -> T { + self.max + } + + pub fn step(&self) -> T { + self.step + } +} + +impl IntRange { + pub fn new(min: i32, max: i32) -> Self { + Self::new_with_step(min, max, 1) + } + + pub fn new_with_step(min: i32, max: i32, step: i32) -> Self { + assert!(min <= max); + assert!(step > 0); + + Self { + min: min, + max: max, + step: step, + } + } +} + +impl IntRange { + pub fn new(min: i64, max: i64) -> Self { + Self::new_with_step(min, max, 1) + } + + pub fn new_with_step(min: i64, max: i64, step: i64) -> Self { + assert!(min <= max); + assert!(step > 0); + + Self { + min: min, + max: max, + step: step, + } + } +} + +impl From<(i32, i32)> for IntRange { + fn from((min, max): (i32, i32)) -> Self { + Self::new(min, max) + } +} + +impl From<(i32, i32, i32)> for IntRange { + fn from((min, max, step): (i32, i32, i32)) -> Self { + Self::new_with_step(min, max, step) + } +} + +impl From<(i64, i64)> for IntRange { + fn from((min, max): (i64, i64)) -> Self { + Self::new(min, max) + } +} + +impl From<(i64, i64, i64)> for IntRange { + fn from((min, max, step): (i64, i64, i64)) -> Self { + Self::new_with_step(min, max, step) + } +} + +impl glib::types::StaticType for IntRange { + fn static_type() -> glib::types::Type { + unsafe { from_glib(ffi::gst_int_range_get_type()) } + } +} + +impl<'a> FromValue<'a> for IntRange { + unsafe fn from_value(v: &'a Value) -> Self { + let min = ffi::gst_value_get_int_range_min(v.to_glib_none().0); + let max = ffi::gst_value_get_int_range_max(v.to_glib_none().0); + let step = ffi::gst_value_get_int_range_step(v.to_glib_none().0); + + Self::new_with_step(min, max, step) + } +} + +impl<'a> FromValueOptional<'a> for IntRange { + unsafe fn from_value_optional(v: &'a Value) -> Option { + Some(Self::from_value(v)) + } +} + +impl SetValue for IntRange { + unsafe fn set_value(v: &mut Value, r: &Self) { + ffi::gst_value_set_int_range_step(v.to_glib_none_mut().0, r.min(), r.max(), r.step()); + } +} + +impl glib::types::StaticType for IntRange { + fn static_type() -> glib::types::Type { + unsafe { from_glib(ffi::gst_int64_range_get_type()) } + } +} + +impl<'a> FromValue<'a> for IntRange { + unsafe fn from_value(v: &'a Value) -> Self { + let min = ffi::gst_value_get_int64_range_min(v.to_glib_none().0); + let max = ffi::gst_value_get_int64_range_max(v.to_glib_none().0); + let step = ffi::gst_value_get_int64_range_step(v.to_glib_none().0); + + Self::new_with_step(min, max, step) + } +} + +impl<'a> FromValueOptional<'a> for IntRange { + unsafe fn from_value_optional(v: &'a Value) -> Option { + Some(Self::from_value(v)) + } +} + +impl SetValue for IntRange { + unsafe fn set_value(v: &mut Value, r: &Self) { + ffi::gst_value_set_int64_range_step(v.to_glib_none_mut().0, r.min(), r.max(), r.step()); + } +} + +#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] +pub struct FractionRange { + min: Fraction, + max: Fraction, +} + +impl FractionRange { + pub fn new, U: Into>(min: T, max: U) -> Self { + let min = min.into(); + let max = max.into(); + + assert!(min <= max); + + FractionRange { + min: min, + max: max, + } + } + + pub fn min(&self) -> Fraction { + self.min + } + + pub fn max(&self) -> Fraction { + self.max + } +} + +impl From<(Fraction, Fraction)> for FractionRange { + fn from((min, max): (Fraction, Fraction)) -> Self { + Self::new(min, max) + } +} + +impl glib::types::StaticType for FractionRange { + fn static_type() -> glib::types::Type { + unsafe { from_glib(ffi::gst_fraction_range_get_type()) } + } +} + +impl<'a> FromValue<'a> for FractionRange { + unsafe fn from_value(v: &'a Value) -> Self { + let min = ffi::gst_value_get_fraction_range_min(v.to_glib_none().0); + let max = ffi::gst_value_get_fraction_range_max(v.to_glib_none().0); + + let min_n = ffi::gst_value_get_fraction_numerator(min); + let min_d = ffi::gst_value_get_fraction_denominator(min); + let max_n = ffi::gst_value_get_fraction_numerator(max); + let max_d = ffi::gst_value_get_fraction_denominator(max); + + Self::new((min_n, min_d), (max_n, max_d)) + } +} + +impl<'a> FromValueOptional<'a> for FractionRange { + unsafe fn from_value_optional(v: &'a Value) -> Option { + Some(Self::from_value(v)) + } +} + +impl SetValue for FractionRange { + unsafe fn set_value(v: &mut Value, r: &Self) { + ffi::gst_value_set_fraction_range_full(v.to_glib_none_mut().0, *r.min().numer(), *r.min().denom(), *r.max().numer(), *r.max().denom()); + } +} + +#[derive(Clone, Debug)] +pub struct Array<'a>(Cow<'a, [glib::Value]>); + +impl<'a> Array<'a> { + pub fn new(values: &[&ToValue]) -> Self { + Array(values.iter().map(|v| v.to_value()).collect()) + } + + pub fn into_owned(self) -> Array<'static> { + Array(self.0.into_owned().into()) + } + + pub fn as_slice(&self) -> &[glib::Value] { + self.0.borrow() + } +} + +impl<'a> From<&'a [&'a ToValue]> for Array<'a> { + fn from(values: &'a [&'a ToValue]) -> Self { + Self::new(values) + } +} + +impl<'a> From<&'a [glib::Value]> for Array<'a> { + fn from(values: &'a [glib::Value]) -> Self { + Array(Cow::Borrowed(values)) + } +} + +impl<'a> FromValue<'a> for Array<'a> { + unsafe fn from_value(v: &'a Value) -> Self { + let arr = (*v.to_glib_none().0).data[0] as *const glib_ffi::GArray; + if arr.is_null() { + Array(Cow::Borrowed(&[])) + } else { + Array(Cow::Borrowed(slice::from_raw_parts((*arr).data as *const glib::Value, (*arr).len as usize))) + } + } +} + +impl<'a> FromValueOptional<'a> for Array<'a> { + unsafe fn from_value_optional(v: &'a Value) -> Option { + Some(Array::from_value(v)) + } +} + +impl<'a> SetValue for Array<'a> { + unsafe fn set_value(v: &mut Value, a: &Self) { + for value in a.as_slice() { + ffi::gst_value_array_append_and_take_value(v.to_glib_none_mut().0, value.to_glib_full() as *mut _); + } + } +} + +impl<'a> glib::types::StaticType for Array<'a> { + fn static_type() -> glib::types::Type { + unsafe { from_glib(ffi::gst_value_array_get_type()) } + } +} + +#[derive(Clone, Debug)] +pub struct List<'a>(Cow<'a, [glib::Value]>); + +impl<'a> List<'a> { + pub fn new(values: &[&ToValue]) -> Self { + List(values.iter().map(|v| v.to_value()).collect()) + } + + pub fn into_owned(self) -> List<'static> { + List(self.0.into_owned().into()) + } + + pub fn as_slice(&self) -> &[glib::Value] { + self.0.borrow() + } +} + +impl<'a> From<&'a [&'a ToValue]> for List<'a> { + fn from(values: &'a [&'a ToValue]) -> Self { + Self::new(values) + } +} + +impl<'a> From<&'a [glib::Value]> for List<'a> { + fn from(values: &'a [glib::Value]) -> Self { + List(Cow::Borrowed(values)) + } +} + +impl<'a> FromValue<'a> for List<'a> { + unsafe fn from_value(v: &'a Value) -> Self { + let arr = (*v.to_glib_none().0).data[0] as *const glib_ffi::GArray; + if arr.is_null() { + List(Cow::Borrowed(&[])) + } else { + List(Cow::Borrowed(slice::from_raw_parts((*arr).data as *const glib::Value, (*arr).len as usize))) + } + } +} + +impl<'a> FromValueOptional<'a> for List<'a> { + unsafe fn from_value_optional(v: &'a Value) -> Option { + Some(List::from_value(v)) + } +} + +impl<'a> SetValue for List<'a> { + unsafe fn set_value(v: &mut Value, a: &Self) { + for value in a.as_slice() { + ffi::gst_value_list_append_and_take_value(v.to_glib_none_mut().0, value.to_glib_full() as *mut _); + } + } +} + +impl<'a> glib::types::StaticType for List<'a> { + fn static_type() -> glib::types::Type { + unsafe { from_glib(ffi::gst_value_list_get_type()) } + } +} + +// TODO: GStreamer value operations