// Take a look at the license at the top of the repository in the LICENSE file. use crate::format::{ CompatibleFormattedValue, FormattedValue, FormattedValueFullRange, FormattedValueIntrinsic, FormattedValueNoneBuilder, NoneSignedBuilder, UnsignedIntoSigned, }; use crate::Format; use crate::GenericFormattedValue; use crate::SeekFlags; use crate::SeekType; use glib::translate::*; use glib::StaticType; use std::fmt; use std::marker::PhantomData; use std::mem; use std::ptr; pub type Segment = FormattedSegment; #[repr(transparent)] #[doc(alias = "GstSegment")] pub struct FormattedSegment(ffi::GstSegment, PhantomData); impl Segment { pub unsafe fn from_ptr<'a>(ptr: *const ffi::GstSegment) -> &'a Segment { assert!(!ptr.is_null()); &*(ptr as *const Self) } pub fn reset_with_format(&mut self, format: Format) { unsafe { ffi::gst_segment_init(self.to_glib_none_mut().0, format.into_glib()); } } pub fn set_format(&mut self, format: Format) { self.0.format = format.into_glib(); } pub fn downcast(self) -> Result, Self> { if T::default_format() == Format::Undefined || T::default_format() == self.format() { Ok(FormattedSegment(self.0, PhantomData)) } else { Err(self) } } pub fn downcast_ref(&self) -> Option<&FormattedSegment> { if T::default_format() == Format::Undefined || T::default_format() == self.format() { Some(unsafe { &*(self as *const FormattedSegment as *const FormattedSegment) }) } else { None } } pub fn downcast_mut(&mut self) -> Option<&mut FormattedSegment> { if T::default_format() == Format::Undefined || T::default_format() == self.format() { Some(unsafe { &mut *(self as *mut FormattedSegment as *mut FormattedSegment) }) } else { None } } } impl FormattedSegment { pub fn new() -> Self { assert_initialized_main_thread!(); let segment = unsafe { let mut segment = mem::MaybeUninit::zeroed(); ffi::gst_segment_init(segment.as_mut_ptr(), T::default_format().into_glib()); segment.assume_init() }; FormattedSegment(segment, PhantomData) } pub fn upcast(self) -> Segment { FormattedSegment(self.0, PhantomData) } pub fn upcast_ref(&self) -> &Segment { unsafe { &*(self as *const FormattedSegment as *const FormattedSegment) } } pub fn reset(&mut self) { unsafe { ffi::gst_segment_init(&mut self.0, T::default_format().into_glib()); } } #[doc(alias = "gst_segment_clip")] pub fn clip( &self, start: impl CompatibleFormattedValue, stop: impl CompatibleFormattedValue, ) -> Option<(T::FullRange, T::FullRange)> { let start = start.try_into_checked_explicit(self.format()).unwrap(); let stop = stop.try_into_checked_explicit(self.format()).unwrap(); unsafe { let mut clip_start = mem::MaybeUninit::uninit(); let mut clip_stop = mem::MaybeUninit::uninit(); let ret = from_glib(ffi::gst_segment_clip( &self.0, start.format().into_glib(), start.into_raw_value() as u64, stop.into_raw_value() as u64, clip_start.as_mut_ptr(), clip_stop.as_mut_ptr(), )); if ret { Some(( T::FullRange::from_raw(self.format(), clip_start.assume_init() as i64), T::FullRange::from_raw(self.format(), clip_stop.assume_init() as i64), )) } else { None } } } #[allow(clippy::too_many_arguments)] #[doc(alias = "gst_segment_do_seek")] pub fn do_seek( &mut self, rate: f64, flags: SeekFlags, start_type: SeekType, start: impl CompatibleFormattedValue, stop_type: SeekType, stop: impl CompatibleFormattedValue, ) -> Option { skip_assert_initialized!(); let start = start.try_into_checked_explicit(self.format()).unwrap(); let stop = stop.try_into_checked_explicit(self.format()).unwrap(); unsafe { let mut update = mem::MaybeUninit::uninit(); let ret = from_glib(ffi::gst_segment_do_seek( &mut self.0, rate, self.format().into_glib(), flags.into_glib(), start_type.into_glib(), start.into_raw_value() as u64, stop_type.into_glib(), stop.into_raw_value() as u64, update.as_mut_ptr(), )); if ret { Some(from_glib(update.assume_init())) } else { None } } } #[doc(alias = "gst_segment_offset_running_time")] pub fn offset_running_time(&mut self, offset: i64) -> Result<(), glib::BoolError> { unsafe { glib::result_from_gboolean!( ffi::gst_segment_offset_running_time( &mut self.0, self.format().into_glib(), offset, ), "Offset is not in the segment" ) } } #[doc(alias = "gst_segment_set_running_time")] pub fn set_running_time( &mut self, running_time: impl CompatibleFormattedValue, ) -> Result<(), glib::BoolError> { let running_time = running_time .try_into_checked_explicit(self.format()) .unwrap(); unsafe { glib::result_from_gboolean!( ffi::gst_segment_set_running_time( &mut self.0, self.format().into_glib(), running_time.into_raw_value() as u64, ), "Running time is not in the segment" ) } } #[doc(alias = "get_flags")] pub fn flags(&self) -> crate::SegmentFlags { unsafe { from_glib(self.0.flags) } } pub fn set_flags(&mut self, flags: crate::SegmentFlags) { self.0.flags = flags.into_glib(); } #[doc(alias = "get_rate")] pub fn rate(&self) -> f64 { self.0.rate } #[allow(clippy::float_cmp)] pub fn set_rate(&mut self, rate: f64) { assert_ne!(rate, 0.0); self.0.rate = rate; } #[doc(alias = "get_applied_rate")] pub fn applied_rate(&self) -> f64 { self.0.applied_rate } #[allow(clippy::float_cmp)] pub fn set_applied_rate(&mut self, applied_rate: f64) { assert_ne!(applied_rate, 0.0); self.0.applied_rate = applied_rate; } #[doc(alias = "get_format")] pub fn format(&self) -> Format { unsafe { from_glib(self.0.format) } } #[doc(alias = "get_base")] pub fn base(&self) -> T::FullRange { unsafe { T::FullRange::from_raw(self.format(), self.0.base as i64) } } pub fn set_base(&mut self, base: impl CompatibleFormattedValue) { let base = base.try_into_checked_explicit(self.format()).unwrap(); self.0.base = unsafe { base.into_raw_value() } as u64; } #[doc(alias = "get_offset")] pub fn offset(&self) -> T::FullRange { unsafe { T::FullRange::from_raw(self.format(), self.0.offset as i64) } } pub fn set_offset(&mut self, offset: impl CompatibleFormattedValue) { let offset = offset.try_into_checked_explicit(self.format()).unwrap(); self.0.offset = unsafe { offset.into_raw_value() } as u64; } #[doc(alias = "get_start")] pub fn start(&self) -> T::FullRange { unsafe { T::FullRange::from_raw(self.format(), self.0.start as i64) } } pub fn set_start(&mut self, start: impl CompatibleFormattedValue) { let start = start.try_into_checked_explicit(self.format()).unwrap(); self.0.start = unsafe { start.into_raw_value() } as u64; } #[doc(alias = "get_stop")] pub fn stop(&self) -> T::FullRange { unsafe { T::FullRange::from_raw(self.format(), self.0.stop as i64) } } pub fn set_stop(&mut self, stop: impl CompatibleFormattedValue) { let stop = stop.try_into_checked_explicit(self.format()).unwrap(); self.0.stop = unsafe { stop.into_raw_value() } as u64; } #[doc(alias = "get_time")] pub fn time(&self) -> T::FullRange { unsafe { T::FullRange::from_raw(self.format(), self.0.time as i64) } } pub fn set_time(&mut self, time: impl CompatibleFormattedValue) { let time = time.try_into_checked_explicit(self.format()).unwrap(); self.0.time = unsafe { time.into_raw_value() } as u64; } #[doc(alias = "get_position")] pub fn position(&self) -> T::FullRange { unsafe { T::FullRange::from_raw(self.format(), self.0.position as i64) } } pub fn set_position(&mut self, position: impl CompatibleFormattedValue) { let position = position.try_into_checked_explicit(self.format()).unwrap(); self.0.position = unsafe { position.into_raw_value() } as u64; } #[doc(alias = "get_duration")] pub fn duration(&self) -> T::FullRange { unsafe { T::FullRange::from_raw(self.format(), self.0.duration as i64) } } pub fn set_duration(&mut self, duration: impl CompatibleFormattedValue) { let duration = duration.try_into_checked_explicit(self.format()).unwrap(); self.0.duration = unsafe { duration.into_raw_value() } as u64; } } impl PartialEq for FormattedSegment { #[inline] #[doc(alias = "gst_segment_is_equal")] fn eq(&self, other: &Self) -> bool { unsafe { from_glib(ffi::gst_segment_is_equal(&self.0, &other.0)) } } } impl FormattedSegment where T: FormattedValueIntrinsic, T::FullRange: FormattedValueNoneBuilder, { #[doc(alias = "gst_segment_position_from_running_time")] pub fn position_from_running_time( &self, running_time: impl CompatibleFormattedValue, ) -> T::FullRange { let running_time = running_time .try_into_checked_explicit(self.format()) .unwrap(); if running_time.is_none() { return T::FullRange::none_for_format(self.format()); } unsafe { T::FullRange::from_raw( self.format(), ffi::gst_segment_position_from_running_time( &self.0, self.format().into_glib(), running_time.into_raw_value() as u64, ) as i64, ) } } #[doc(alias = "gst_segment_position_from_stream_time")] pub fn position_from_stream_time( &self, stream_time: impl CompatibleFormattedValue, ) -> T::FullRange { let stream_time = stream_time .try_into_checked_explicit(self.format()) .unwrap(); if stream_time.is_none() { return T::FullRange::none_for_format(self.format()); } unsafe { T::FullRange::from_raw( self.format(), ffi::gst_segment_position_from_stream_time( &self.0, self.format().into_glib(), stream_time.into_raw_value() as u64, ) as i64, ) } } #[doc(alias = "gst_segment_to_running_time")] pub fn to_running_time(&self, position: impl CompatibleFormattedValue) -> T::FullRange { let position = position.try_into_checked_explicit(self.format()).unwrap(); if position.is_none() { return T::FullRange::none_for_format(self.format()); } unsafe { T::FullRange::from_raw( self.format(), ffi::gst_segment_to_running_time( &self.0, self.format().into_glib(), position.into_raw_value() as u64, ) as i64, ) } } #[doc(alias = "gst_segment_to_stream_time")] pub fn to_stream_time(&self, position: impl CompatibleFormattedValue) -> T::FullRange { let position = position.try_into_checked_explicit(self.format()).unwrap(); if position.is_none() { return T::FullRange::none_for_format(self.format()); } unsafe { T::FullRange::from_raw( self.format(), ffi::gst_segment_to_stream_time( &self.0, self.format().into_glib(), position.into_raw_value() as u64, ) as i64, ) } } } impl FormattedSegment where T: FormattedValueIntrinsic, T::FullRange: UnsignedIntoSigned, T::FullRange: NoneSignedBuilder::Signed>, { #[doc(alias = "gst_segment_position_from_running_time_full")] pub fn position_from_running_time_full( &self, running_time: impl CompatibleFormattedValue, ) -> ::Signed { let running_time = running_time .try_into_checked_explicit(self.format()) .unwrap(); if running_time.is_none() { return T::FullRange::none_signed_for_format(self.format()); } unsafe { let mut position = mem::MaybeUninit::uninit(); let sign = ffi::gst_segment_position_from_running_time_full( &self.0, self.format().into_glib(), running_time.into_raw_value() as u64, position.as_mut_ptr(), ); T::FullRange::from_raw(self.format(), position.assume_init() as i64).into_signed(sign) } } #[doc(alias = "gst_segment_position_from_stream_time_full")] pub fn position_from_stream_time_full( &self, stream_time: impl CompatibleFormattedValue, ) -> ::Signed { let stream_time = stream_time .try_into_checked_explicit(self.format()) .unwrap(); if stream_time.is_none() { return T::FullRange::none_signed_for_format(self.format()); } unsafe { let mut position = mem::MaybeUninit::uninit(); let sign = ffi::gst_segment_position_from_stream_time_full( &self.0, self.format().into_glib(), stream_time.into_raw_value() as u64, position.as_mut_ptr(), ); T::FullRange::from_raw(self.format(), position.assume_init() as i64).into_signed(sign) } } #[doc(alias = "gst_segment_to_running_time_full")] pub fn to_running_time_full( &self, position: impl CompatibleFormattedValue, ) -> ::Signed { let position = position.try_into_checked_explicit(self.format()).unwrap(); if position.is_none() { return T::FullRange::none_signed_for_format(self.format()); } unsafe { let mut running_time = mem::MaybeUninit::uninit(); let sign = ffi::gst_segment_to_running_time_full( &self.0, self.format().into_glib(), position.into_raw_value() as u64, running_time.as_mut_ptr(), ); T::FullRange::from_raw(self.format(), running_time.assume_init() as i64) .into_signed(sign) } } #[doc(alias = "gst_segment_to_stream_time_full")] pub fn to_stream_time_full( &self, position: impl CompatibleFormattedValue, ) -> ::Signed { let position = position.try_into_checked_explicit(self.format()).unwrap(); if position.is_none() { return T::FullRange::none_signed_for_format(self.format()); } unsafe { let mut stream_time = mem::MaybeUninit::uninit(); let sign = ffi::gst_segment_to_stream_time_full( &self.0, self.format().into_glib(), position.into_raw_value() as u64, stream_time.as_mut_ptr(), ); T::FullRange::from_raw(self.format(), stream_time.assume_init() as i64) .into_signed(sign) } } } impl Eq for FormattedSegment {} unsafe impl Send for FormattedSegment {} unsafe impl Sync for FormattedSegment {} impl Clone for FormattedSegment { fn clone(&self) -> Self { unsafe { FormattedSegment(ptr::read(&self.0), PhantomData) } } } impl AsRef for FormattedSegment { fn as_ref(&self) -> &Segment { unsafe { &*(self as *const FormattedSegment as *const FormattedSegment) } } } impl fmt::Debug for FormattedSegment { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use crate::utils::Displayable; let segment = self.as_ref(); match segment.format() { Format::Undefined => f .debug_struct("Segment") .field("format", &Format::Undefined) .finish(), Format::Time => { let segment = segment.downcast_ref::().unwrap(); f.debug_struct("Segment") .field("format", &Format::Time) .field("start", &segment.start().display()) .field("offset", &segment.offset().display()) .field("stop", &segment.stop().display()) .field("rate", &segment.rate()) .field("applied_rate", &segment.applied_rate()) .field("flags", &segment.flags()) .field("time", &segment.time().display()) .field("base", &segment.base().display()) .field("position", &segment.position().display()) .field("duration", &segment.duration().display()) .finish() } _ => f .debug_struct("Segment") .field("format", &segment.format()) .field("start", &segment.start()) .field("offset", &segment.offset()) .field("stop", &segment.stop()) .field("rate", &segment.rate()) .field("applied_rate", &segment.applied_rate()) .field("flags", &segment.flags()) .field("time", &segment.time()) .field("base", &segment.base()) .field("position", &segment.position()) .field("duration", &segment.duration()) .finish(), } } } impl Default for FormattedSegment { fn default() -> Self { Self::new() } } impl glib::types::StaticType for FormattedSegment { fn static_type() -> glib::types::Type { unsafe { glib::translate::from_glib(ffi::gst_segment_get_type()) } } } impl glib::value::ValueType for Segment { type Type = Self; } #[doc(hidden)] unsafe impl<'a> glib::value::FromValue<'a> for Segment { type Checker = glib::value::GenericValueTypeOrNoneChecker; unsafe fn from_value(value: &'a glib::Value) -> Self { skip_assert_initialized!(); from_glib_none( glib::gobject_ffi::g_value_get_boxed(value.to_glib_none().0) as *mut ffi::GstSegment ) } } #[doc(hidden)] unsafe impl<'a> glib::value::FromValue<'a> for &'a Segment { type Checker = glib::value::GenericValueTypeOrNoneChecker; unsafe fn from_value(value: &'a glib::Value) -> Self { skip_assert_initialized!(); Segment::from_ptr( glib::gobject_ffi::g_value_get_boxed(value.to_glib_none().0) as *const ffi::GstSegment ) } } #[doc(hidden)] impl glib::value::ToValue for FormattedSegment { fn to_value(&self) -> glib::Value { let mut value = glib::Value::for_value_type::(); unsafe { glib::gobject_ffi::g_value_set_boxed( value.to_glib_none_mut().0, self.to_glib_none().0 as *mut _, ) } value } fn value_type(&self) -> glib::Type { Self::static_type() } } #[doc(hidden)] impl glib::value::ToValueOptional for FormattedSegment { fn to_value_optional(s: Option<&Self>) -> glib::Value { skip_assert_initialized!(); let mut value = glib::Value::for_value_type::(); unsafe { glib::gobject_ffi::g_value_set_boxed( value.to_glib_none_mut().0, s.to_glib_none().0 as *mut _, ) } value } } impl From> for glib::Value { fn from(v: FormattedSegment) -> glib::Value { skip_assert_initialized!(); glib::value::ToValue::to_value(&v) } } #[doc(hidden)] impl glib::translate::GlibPtrDefault for FormattedSegment { type GlibType = *mut ffi::GstSegment; } #[doc(hidden)] impl<'a, T: FormattedValueIntrinsic> glib::translate::ToGlibPtr<'a, *const ffi::GstSegment> for FormattedSegment { type Storage = &'a FormattedSegment; fn to_glib_none(&'a self) -> glib::translate::Stash<'a, *const ffi::GstSegment, Self> { glib::translate::Stash(&self.0, self) } fn to_glib_full(&self) -> *const ffi::GstSegment { unimplemented!() } } #[doc(hidden)] impl<'a, T: FormattedValueIntrinsic> glib::translate::ToGlibPtrMut<'a, *mut ffi::GstSegment> for FormattedSegment { type Storage = &'a mut FormattedSegment; #[inline] fn to_glib_none_mut(&'a mut self) -> glib::translate::StashMut<'a, *mut ffi::GstSegment, Self> { glib::translate::StashMut(&mut self.0, self) } } #[doc(hidden)] impl glib::translate::FromGlibPtrNone<*const ffi::GstSegment> for Segment { #[inline] unsafe fn from_glib_none(ptr: *const ffi::GstSegment) -> Self { FormattedSegment(ptr::read(ptr), PhantomData) } } #[doc(hidden)] impl glib::translate::FromGlibPtrNone<*mut ffi::GstSegment> for Segment { #[inline] unsafe fn from_glib_none(ptr: *mut ffi::GstSegment) -> Self { FormattedSegment(ptr::read(ptr), PhantomData) } } #[doc(hidden)] impl glib::translate::FromGlibPtrBorrow<*mut ffi::GstSegment> for Segment { #[inline] unsafe fn from_glib_borrow(ptr: *mut ffi::GstSegment) -> Borrowed { Borrowed::new(FormattedSegment(ptr::read(ptr), PhantomData)) } } #[doc(hidden)] impl glib::translate::FromGlibPtrFull<*mut ffi::GstSegment> for Segment { #[inline] unsafe fn from_glib_full(ptr: *mut ffi::GstSegment) -> Self { let segment = from_glib_none(ptr); glib::ffi::g_free(ptr as *mut _); segment } }