From 90bb458e64a657ca8aa2c4aa3f4dc5f62042f981 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Laignel?= Date: Tue, 27 Oct 2020 18:27:16 +0100 Subject: [PATCH] Rework ClockTime & FormattedValues --- examples/src/bin/discoverer.rs | 2 +- examples/src/bin/gtksink.rs | 4 +- examples/src/bin/gtkvideooverlay.rs | 4 +- gstreamer/src/buffer.rs | 77 +- gstreamer/src/buffer_pool.rs | 4 +- gstreamer/src/buffer_serde.rs | 27 +- gstreamer/src/bufferlist.rs | 39 +- gstreamer/src/bufferlist_serde.rs | 29 +- gstreamer/src/bus.rs | 12 +- gstreamer/src/clock.rs | 58 +- gstreamer/src/clock_time.rs | 905 ++++++++++++++--------- gstreamer/src/clock_time_serde.rs | 93 +-- gstreamer/src/element.rs | 35 +- gstreamer/src/event.rs | 12 +- gstreamer/src/format.rs | 657 +++++++--------- gstreamer/src/format_serde.rs | 32 +- gstreamer/src/lib.rs | 31 +- gstreamer/src/message.rs | 12 +- gstreamer/src/meta.rs | 14 +- gstreamer/src/pad.rs | 40 +- gstreamer/src/query.rs | 17 +- gstreamer/src/sample.rs | 4 +- gstreamer/src/sample_serde.rs | 44 +- gstreamer/src/segment.rs | 269 ++++--- gstreamer/src/segment_serde.rs | 83 ++- gstreamer/src/subclass/clock.rs | 35 +- gstreamer/src/subclass/element.rs | 2 +- gstreamer/src/tags.rs | 25 +- gstreamer/src/tags_serde.rs | 8 +- gstreamer/src/utils.rs | 8 + tutorials/src/bin/basic-tutorial-13.rs | 4 +- tutorials/src/bin/basic-tutorial-4.rs | 9 +- tutorials/src/bin/basic-tutorial-5.rs | 14 +- tutorials/src/bin/basic-tutorial-9.rs | 2 +- tutorials/src/bin/playback-tutorial-4.rs | 2 +- 35 files changed, 1389 insertions(+), 1224 deletions(-) diff --git a/examples/src/bin/discoverer.rs b/examples/src/bin/discoverer.rs index 1eba09575..7c37c0ba9 100644 --- a/examples/src/bin/discoverer.rs +++ b/examples/src/bin/discoverer.rs @@ -56,7 +56,7 @@ fn print_discoverer_info(info: &DiscovererInfo) -> Result<(), Error> { .uri() .ok_or(DiscovererError("URI should not be null"))?; println!("URI: {}", uri); - println!("Duration: {}", info.duration()); + println!("Duration: {}", info.duration().display()); print_tags(info); print_stream_info( &info diff --git a/examples/src/bin/gtksink.rs b/examples/src/bin/gtksink.rs index b766d7f1f..6e775bcee 100644 --- a/examples/src/bin/gtksink.rs +++ b/examples/src/bin/gtksink.rs @@ -89,9 +89,7 @@ fn create_ui(app: >k::Application) { }; // Query the current playing position from the underlying pipeline. - let position = pipeline - .query_position::() - .unwrap_or_else(|| 0.into()); + let position = pipeline.query_position::(); // Display the playing position in the gui. label.set_text(&format!("Position: {:.0}", position)); // Tell the callback to continue calling this closure. diff --git a/examples/src/bin/gtkvideooverlay.rs b/examples/src/bin/gtkvideooverlay.rs index e49a29943..24fb9fffd 100644 --- a/examples/src/bin/gtkvideooverlay.rs +++ b/examples/src/bin/gtkvideooverlay.rs @@ -194,9 +194,7 @@ fn create_ui(app: >k::Application) { }; // Query the current playing position from the underlying pipeline. - let position = pipeline - .query_position::() - .unwrap_or_else(|| 0.into()); + let position = pipeline.query_position::(); // Display the playing position in the gui. label.set_text(&format!("Position: {:.0}", position)); // Tell the timeout to continue calling this callback. diff --git a/gstreamer/src/buffer.rs b/gstreamer/src/buffer.rs index 2f3878987..680c5f47b 100644 --- a/gstreamer/src/buffer.rs +++ b/gstreamer/src/buffer.rs @@ -351,25 +351,25 @@ impl BufferRef { } #[doc(alias = "get_pts")] - pub fn pts(&self) -> ClockTime { + pub fn pts(&self) -> Option { unsafe { from_glib(self.0.pts) } } - pub fn set_pts(&mut self, pts: ClockTime) { - self.0.pts = pts.into_glib(); + pub fn set_pts(&mut self, pts: impl Into>) { + self.0.pts = pts.into().into_glib(); } #[doc(alias = "get_dts")] - pub fn dts(&self) -> ClockTime { + pub fn dts(&self) -> Option { unsafe { from_glib(self.0.dts) } } - pub fn set_dts(&mut self, dts: ClockTime) { - self.0.dts = dts.into_glib(); + pub fn set_dts(&mut self, dts: impl Into>) { + self.0.dts = dts.into().into_glib(); } #[doc(alias = "get_dts_or_pts")] - pub fn dts_or_pts(&self) -> ClockTime { + pub fn dts_or_pts(&self) -> Option { let val = self.dts(); if val.is_none() { self.pts() @@ -379,12 +379,12 @@ impl BufferRef { } #[doc(alias = "get_duration")] - pub fn duration(&self) -> ClockTime { + pub fn duration(&self) -> Option { unsafe { from_glib(self.0.duration) } } - pub fn set_duration(&mut self, duration: ClockTime) { - self.0.duration = duration.into_glib(); + pub fn set_duration(&mut self, duration: impl Into>) { + self.0.duration = duration.into().into_glib(); } #[doc(alias = "get_flags")] @@ -926,6 +926,7 @@ impl Eq for Buffer {} impl fmt::Debug for BufferRef { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use crate::utils::Displayable; use std::cell::RefCell; struct DebugIter(RefCell); @@ -940,9 +941,9 @@ impl fmt::Debug for BufferRef { f.debug_struct("Buffer") .field("ptr", unsafe { &self.as_ptr() }) - .field("pts", &self.pts().to_string()) - .field("dts", &self.dts().to_string()) - .field("duration", &self.duration().to_string()) + .field("pts", &self.pts().display().to_string()) + .field("dts", &self.dts().display().to_string()) + .field("duration", &self.duration().display().to_string()) .field("size", &self.size()) .field("offset", &self.offset()) .field("offset_end", &self.offset_end()) @@ -1149,17 +1150,17 @@ mod tests { { let buffer = buffer.get_mut().unwrap(); - buffer.set_pts(1.into()); - buffer.set_dts(2.into()); + buffer.set_pts(ClockTime::NSECOND); + buffer.set_dts(2 * ClockTime::NSECOND); buffer.set_offset(3); buffer.set_offset_end(4); - buffer.set_duration(5.into()); + buffer.set_duration(Some(5 * ClockTime::NSECOND)); } - assert_eq!(buffer.pts(), 1.into()); - assert_eq!(buffer.dts(), 2.into()); + assert_eq!(buffer.pts(), Some(ClockTime::NSECOND)); + assert_eq!(buffer.dts(), Some(2 * ClockTime::NSECOND)); assert_eq!(buffer.offset(), 3); assert_eq!(buffer.offset_end(), 4); - assert_eq!(buffer.duration(), 5.into()); + assert_eq!(buffer.duration(), Some(5 * ClockTime::NSECOND)); } #[test] @@ -1174,7 +1175,7 @@ mod tests { assert_ne!(buffer.get_mut(), None); { let buffer = buffer.get_mut().unwrap(); - buffer.set_pts(1.into()); + buffer.set_pts(Some(ClockTime::NSECOND)); } let mut buffer2 = buffer.clone(); @@ -1190,15 +1191,15 @@ mod tests { assert_ne!(buffer2.as_ptr(), buffer.as_ptr()); } - buffer2.set_pts(2.into()); + buffer2.set_pts(Some(2 * ClockTime::NSECOND)); let mut data = buffer2.map_writable().unwrap(); assert_eq!(data.as_slice(), vec![1, 2, 3, 4].as_slice()); data.as_mut_slice()[0] = 0; } - assert_eq!(buffer.pts(), 1.into()); - assert_eq!(buffer2.pts(), 2.into()); + assert_eq!(buffer.pts(), Some(ClockTime::NSECOND)); + assert_eq!(buffer2.pts(), Some(2 * ClockTime::NSECOND)); { let data = buffer.map_readable().unwrap(); @@ -1331,14 +1332,14 @@ mod tests { crate::ReferenceTimestampMeta::add( buffer, &crate::Caps::builder("foo/bar").build(), - crate::ClockTime::from(0), - crate::CLOCK_TIME_NONE, + ClockTime::ZERO, + ClockTime::NONE, ); crate::ReferenceTimestampMeta::add( buffer, &crate::Caps::builder("foo/bar").build(), - crate::SECOND, - crate::CLOCK_TIME_NONE, + ClockTime::SECOND, + ClockTime::NONE, ); } @@ -1351,7 +1352,10 @@ mod tests { true }); - assert_eq!(&[crate::ClockTime::from(0), crate::SECOND][..], &res[..]); + assert_eq!( + &[Some(ClockTime::ZERO), Some(ClockTime::SECOND)][..], + &res[..] + ); } #[cfg(any(feature = "v1_14", feature = "dox"))] @@ -1366,14 +1370,14 @@ mod tests { crate::ReferenceTimestampMeta::add( buffer, &crate::Caps::builder("foo/bar").build(), - crate::ClockTime::from(0), - crate::CLOCK_TIME_NONE, + ClockTime::ZERO, + ClockTime::NONE, ); crate::ReferenceTimestampMeta::add( buffer, &crate::Caps::builder("foo/bar").build(), - crate::SECOND, - crate::CLOCK_TIME_NONE, + ClockTime::SECOND, + ClockTime::NONE, ); } @@ -1383,14 +1387,17 @@ mod tests { .downcast_ref::() .unwrap(); res.push(meta.timestamp()); - if meta.timestamp() == crate::SECOND { + if let Some(ClockTime::SECOND) = meta.timestamp() { Ok(false) } else { Ok(true) } }); - assert_eq!(&[crate::ClockTime::from(0), crate::SECOND][..], &res[..]); + assert_eq!( + &[Some(ClockTime::ZERO), Some(ClockTime::SECOND)][..], + &res[..] + ); let mut res = vec![]; buffer.foreach_meta(|meta| { @@ -1401,6 +1408,6 @@ mod tests { true }); - assert_eq!(&[crate::ClockTime::from(0)][..], &res[..]); + assert_eq!(&[Some(ClockTime::ZERO)][..], &res[..]); } } diff --git a/gstreamer/src/buffer_pool.rs b/gstreamer/src/buffer_pool.rs index 675e957b2..b9a30a328 100644 --- a/gstreamer/src/buffer_pool.rs +++ b/gstreamer/src/buffer_pool.rs @@ -214,8 +214,8 @@ impl BufferPoolAcquireParams { unsafe { BufferPoolAcquireParams(ffi::GstBufferPoolAcquireParams { format: start.format().into_glib(), - start: start.to_raw_value(), - stop: stop.to_raw_value(), + start: start.into_raw_value(), + stop: stop.into_raw_value(), flags: flags.into_glib(), _gst_reserved: [ptr::null_mut(); 4], }) diff --git a/gstreamer/src/buffer_serde.rs b/gstreamer/src/buffer_serde.rs index a128c2f20..1f69a6241 100644 --- a/gstreamer/src/buffer_serde.rs +++ b/gstreamer/src/buffer_serde.rs @@ -40,9 +40,9 @@ impl<'a> Serialize for Buffer { #[derive(serde::Deserialize)] struct BufferDe { - pts: ClockTime, - dts: ClockTime, - duration: ClockTime, + pts: Option, + dts: Option, + duration: Option, offset: u64, offset_end: u64, flags: BufferFlags, @@ -77,6 +77,7 @@ impl<'de> Deserialize<'de> for Buffer { mod tests { use crate::Buffer; use crate::BufferFlags; + use crate::ClockTime; #[test] fn test_serialize() { @@ -85,10 +86,10 @@ mod tests { let mut buffer = Buffer::from_slice(vec![1, 2, 3, 4]); { let buffer = buffer.get_mut().unwrap(); - buffer.set_pts(1.into()); + buffer.set_pts(Some(ClockTime::NSECOND)); buffer.set_offset(3); buffer.set_offset_end(4); - buffer.set_duration(5.into()); + buffer.set_duration(5 * ClockTime::NSECOND); buffer.set_flags(BufferFlags::LIVE | BufferFlags::DISCONT); } @@ -149,11 +150,11 @@ mod tests { ) "#; let buffer: Buffer = ron::de::from_str(buffer_ron).unwrap(); - assert_eq!(buffer.pts(), 1.into()); - assert_eq!(buffer.dts(), None.into()); + assert_eq!(buffer.pts(), Some(ClockTime::NSECOND)); + assert_eq!(buffer.dts(), crate::ClockTime::NONE); assert_eq!(buffer.offset(), 3); assert_eq!(buffer.offset_end(), 4); - assert_eq!(buffer.duration(), 5.into()); + assert_eq!(buffer.duration(), Some(5 * ClockTime::NSECOND)); assert_eq!(buffer.flags(), BufferFlags::LIVE | BufferFlags::DISCONT); { let data = buffer.map_readable().unwrap(); @@ -172,11 +173,11 @@ mod tests { } "#; let buffer: Buffer = serde_json::from_str(buffer_json).unwrap(); - assert_eq!(buffer.pts(), 1.into()); - assert_eq!(buffer.dts(), None.into()); + assert_eq!(buffer.pts(), Some(ClockTime::NSECOND)); + assert_eq!(buffer.dts(), crate::ClockTime::NONE); assert_eq!(buffer.offset(), 3); assert_eq!(buffer.offset_end(), 4); - assert_eq!(buffer.duration(), 5.into()); + assert_eq!(buffer.duration(), Some(5 * ClockTime::NSECOND)); assert_eq!(buffer.flags(), BufferFlags::LIVE | BufferFlags::DISCONT); { let data = buffer.map_readable().unwrap(); @@ -191,10 +192,10 @@ mod tests { let mut buffer = Buffer::from_slice(vec![1, 2, 3, 4]); { let buffer = buffer.get_mut().unwrap(); - buffer.set_pts(1.into()); + buffer.set_pts(Some(ClockTime::NSECOND)); buffer.set_offset(3); buffer.set_offset_end(4); - buffer.set_duration(5.into()); + buffer.set_duration(5 * ClockTime::NSECOND); buffer.set_flags(BufferFlags::LIVE | BufferFlags::DISCONT); } diff --git a/gstreamer/src/bufferlist.rs b/gstreamer/src/bufferlist.rs index 6da6e280b..c6fed6117 100644 --- a/gstreamer/src/bufferlist.rs +++ b/gstreamer/src/bufferlist.rs @@ -185,17 +185,20 @@ impl fmt::Debug for BufferList { impl fmt::Debug for BufferListRef { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use crate::clock_time::ClockTime; + use crate::utils::Displayable; + let size = self.iter().map(|b| b.size()).sum::(); let (pts, dts) = self .get(0) .map(|b| (b.pts(), b.dts())) - .unwrap_or((crate::ClockTime::none(), crate::ClockTime::none())); + .unwrap_or((ClockTime::NONE, ClockTime::NONE)); f.debug_struct("BufferList") .field("ptr", unsafe { &self.as_ptr() }) .field("buffers", &self.len()) - .field("pts", &pts.to_string()) - .field("dts", &dts.to_string()) + .field("pts", &pts.display().to_string()) + .field("dts", &dts.display().to_string()) .field("size", &size) .finish() } @@ -272,6 +275,7 @@ define_iter!(IterOwned, Buffer, |list: &BufferListRef, idx| { #[cfg(test)] mod tests { use super::*; + use crate::ClockTime; #[test] fn test_foreach() { @@ -281,11 +285,11 @@ mod tests { { let buffer_list = buffer_list.get_mut().unwrap(); let mut buffer = Buffer::new(); - buffer.get_mut().unwrap().set_pts(crate::ClockTime::from(0)); + buffer.get_mut().unwrap().set_pts(ClockTime::ZERO); buffer_list.add(buffer); let mut buffer = Buffer::new(); - buffer.get_mut().unwrap().set_pts(crate::SECOND); + buffer.get_mut().unwrap().set_pts(ClockTime::SECOND); buffer_list.add(buffer); } @@ -296,7 +300,10 @@ mod tests { true }); - assert_eq!(res, &[(crate::ClockTime::from(0), 0), (crate::SECOND, 1)]); + assert_eq!( + res, + &[(Some(ClockTime::ZERO), 0), (Some(ClockTime::SECOND), 1)] + ); } #[test] @@ -307,15 +314,15 @@ mod tests { { let buffer_list = buffer_list.get_mut().unwrap(); let mut buffer = Buffer::new(); - buffer.get_mut().unwrap().set_pts(crate::ClockTime::from(0)); + buffer.get_mut().unwrap().set_pts(ClockTime::ZERO); buffer_list.add(buffer); let mut buffer = Buffer::new(); - buffer.get_mut().unwrap().set_pts(crate::SECOND); + buffer.get_mut().unwrap().set_pts(ClockTime::SECOND); buffer_list.add(buffer); let mut buffer = Buffer::new(); - buffer.get_mut().unwrap().set_pts(2 * crate::SECOND); + buffer.get_mut().unwrap().set_pts(2 * ClockTime::SECOND); buffer_list.add(buffer); } @@ -323,13 +330,13 @@ mod tests { buffer_list.get_mut().unwrap().foreach_mut(|buffer, idx| { res.push((buffer.pts(), idx)); - if buffer.pts() == crate::ClockTime::from(0) { + if let Some(ClockTime::ZERO) = buffer.pts() { Ok(Some(buffer)) - } else if buffer.pts() == crate::SECOND { + } else if let Some(ClockTime::SECOND) = buffer.pts() { Ok(None) } else { let mut new_buffer = Buffer::new(); - new_buffer.get_mut().unwrap().set_pts(3 * crate::SECOND); + new_buffer.get_mut().unwrap().set_pts(3 * ClockTime::SECOND); Ok(Some(new_buffer)) } }); @@ -337,9 +344,9 @@ mod tests { assert_eq!( res, &[ - (crate::ClockTime::from(0), 0), - (crate::SECOND, 1), - (2 * crate::SECOND, 1) + (Some(ClockTime::ZERO), 0), + (Some(ClockTime::SECOND), 1), + (Some(2 * ClockTime::SECOND), 1) ] ); @@ -352,7 +359,7 @@ mod tests { assert_eq!( res, - &[(crate::ClockTime::from(0), 0), (3 * crate::SECOND, 1)] + &[(Some(ClockTime::ZERO), 0), (Some(3 * ClockTime::SECOND), 1)] ); } } diff --git a/gstreamer/src/bufferlist_serde.rs b/gstreamer/src/bufferlist_serde.rs index becdcac76..f1f648c5a 100644 --- a/gstreamer/src/bufferlist_serde.rs +++ b/gstreamer/src/bufferlist_serde.rs @@ -62,6 +62,7 @@ impl<'de> Deserialize<'de> for BufferList { #[cfg(test)] mod tests { use crate::BufferList; + use crate::ClockTime; #[test] fn test_serialize() { @@ -76,20 +77,20 @@ mod tests { let mut buffer = Buffer::from_slice(vec![1, 2, 3, 4]); { let buffer = buffer.get_mut().unwrap(); - buffer.set_pts(1.into()); + buffer.set_pts(ClockTime::NSECOND); buffer.set_offset(0); buffer.set_offset_end(4); - buffer.set_duration(4.into()); + buffer.set_duration(4 * ClockTime::NSECOND); } buffer_list.add(buffer); let mut buffer = Buffer::from_slice(vec![5, 6]); { let buffer = buffer.get_mut().unwrap(); - buffer.set_pts(5.into()); + buffer.set_pts(5 * ClockTime::NSECOND); buffer.set_offset(4); buffer.set_offset_end(6); - buffer.set_duration(2.into()); + buffer.set_duration(2 * ClockTime::NSECOND); } buffer_list.add(buffer); } @@ -163,15 +164,15 @@ mod tests { let buffer_list: BufferList = ron::de::from_str(buffer_list_ron).unwrap(); let mut iter = buffer_list.iter(); let buffer = iter.next().unwrap(); - assert_eq!(buffer.pts(), 1.into()); - assert_eq!(buffer.dts(), None.into()); + assert_eq!(buffer.pts(), Some(ClockTime::NSECOND)); + assert_eq!(buffer.dts(), None); { let data = buffer.map_readable().unwrap(); assert_eq!(data.as_slice(), vec![1, 2, 3, 4].as_slice()); } let buffer = iter.next().unwrap(); - assert_eq!(buffer.pts(), 5.into()); + assert_eq!(buffer.pts(), Some(5 * ClockTime::NSECOND)); { let data = buffer.map_readable().unwrap(); assert_eq!(data.as_slice(), vec![5, 6].as_slice()); @@ -191,20 +192,20 @@ mod tests { let mut buffer = Buffer::from_slice(vec![1, 2, 3, 4]); { let buffer = buffer.get_mut().unwrap(); - buffer.set_pts(1.into()); + buffer.set_pts(ClockTime::NSECOND); buffer.set_offset(0); buffer.set_offset_end(4); - buffer.set_duration(4.into()); + buffer.set_duration(4 * ClockTime::NSECOND); } buffer_list.add(buffer); let mut buffer = Buffer::from_slice(vec![5, 6]); { let buffer = buffer.get_mut().unwrap(); - buffer.set_pts(5.into()); + buffer.set_pts(5 * ClockTime::NSECOND); buffer.set_offset(4); buffer.set_offset_end(6); - buffer.set_duration(2.into()); + buffer.set_duration(2 * ClockTime::NSECOND); } buffer_list.add(buffer); } @@ -213,15 +214,15 @@ mod tests { let buffer_list: BufferList = ron::de::from_str(buffer_list_ser.as_str()).unwrap(); let mut iter = buffer_list.iter(); let buffer = iter.next().unwrap(); - assert_eq!(buffer.pts(), 1.into()); - assert_eq!(buffer.dts(), None.into()); + assert_eq!(buffer.pts(), Some(ClockTime::NSECOND)); + assert_eq!(buffer.dts(), None); { let data = buffer.map_readable().unwrap(); assert_eq!(data.as_slice(), vec![1, 2, 3, 4].as_slice()); } let buffer = iter.next().unwrap(); - assert_eq!(buffer.pts(), 5.into()); + assert_eq!(buffer.pts(), Some(5 * ClockTime::NSECOND)); { let data = buffer.map_readable().unwrap(); assert_eq!(data.as_slice(), vec![5, 6].as_slice()); diff --git a/gstreamer/src/bus.rs b/gstreamer/src/bus.rs index 766feb801..d8907b9fd 100644 --- a/gstreamer/src/bus.rs +++ b/gstreamer/src/bus.rs @@ -203,10 +203,10 @@ impl Bus { } pub fn iter(&self) -> Iter { - self.iter_timed(0.into()) + self.iter_timed(Some(crate::ClockTime::ZERO)) } - pub fn iter_timed(&self, timeout: crate::ClockTime) -> Iter { + pub fn iter_timed(&self, timeout: Option) -> Iter { Iter { bus: self, timeout } } @@ -214,12 +214,12 @@ impl Bus { &'a self, msg_types: &'a [MessageType], ) -> impl Iterator + 'a { - self.iter_timed_filtered(0.into(), msg_types) + self.iter_timed_filtered(Some(crate::ClockTime::ZERO), msg_types) } pub fn iter_timed_filtered<'a>( &'a self, - timeout: crate::ClockTime, + timeout: Option, msg_types: &'a [MessageType], ) -> impl Iterator + 'a { self.iter_timed(timeout) @@ -228,7 +228,7 @@ impl Bus { pub fn timed_pop_filtered( &self, - timeout: crate::ClockTime, + timeout: Option, msg_types: &[MessageType], ) -> Option { loop { @@ -267,7 +267,7 @@ impl Bus { #[derive(Debug)] pub struct Iter<'a> { bus: &'a Bus, - timeout: crate::ClockTime, + timeout: Option, } impl<'a> Iterator for Iter<'a> { diff --git a/gstreamer/src/clock.rs b/gstreamer/src/clock.rs index 55efefb85..a3e932ad6 100644 --- a/gstreamer/src/clock.rs +++ b/gstreamer/src/clock.rs @@ -35,7 +35,7 @@ glib::wrapper! { impl ClockId { #[doc(alias = "get_time")] #[doc(alias = "gst_clock_id_get_time")] - pub fn time(&self) -> ClockTime { + pub fn time(&self) -> Option { unsafe { from_glib(ffi::gst_clock_id_get_time(self.to_glib_none().0)) } } @@ -135,9 +135,11 @@ impl SingleShotClockId { #[doc(alias = "gst_clock_id_wait_async")] pub fn wait_async(&self, func: F) -> Result where - F: FnOnce(&Clock, ClockTime, &ClockId) + Send + 'static, + F: FnOnce(&Clock, Option, &ClockId) + Send + 'static, { - unsafe extern "C" fn trampoline( + unsafe extern "C" fn trampoline< + F: FnOnce(&Clock, Option, &ClockId) + Send + 'static, + >( clock: *mut ffi::GstClock, time: ffi::GstClockTime, id: gpointer, @@ -156,7 +158,7 @@ impl SingleShotClockId { } unsafe extern "C" fn destroy_notify< - F: FnOnce(&Clock, ClockTime, &ClockId) + Send + 'static, + F: FnOnce(&Clock, Option, &ClockId) + Send + 'static, >( ptr: gpointer, ) { @@ -179,7 +181,13 @@ impl SingleShotClockId { pub fn wait_async_future( &self, ) -> Result< - Pin> + Send + 'static>>, + Pin< + Box< + dyn Future, ClockId), ClockError>> + + Send + + 'static, + >, + >, ClockError, > { use futures_channel::oneshot; @@ -234,7 +242,7 @@ impl PeriodicClockId { pub fn interval(&self) -> ClockTime { unsafe { let ptr: *mut ffi::GstClockEntry = self.to_glib_none().0 as *mut _; - from_glib((*ptr).interval) + Option::<_>::from_glib((*ptr).interval).expect("undefined interval") } } @@ -245,9 +253,11 @@ impl PeriodicClockId { #[doc(alias = "gst_clock_id_wait_async")] pub fn wait_async(&self, func: F) -> Result where - F: Fn(&Clock, ClockTime, &ClockId) + Send + 'static, + F: Fn(&Clock, Option, &ClockId) + Send + 'static, { - unsafe extern "C" fn trampoline( + unsafe extern "C" fn trampoline< + F: Fn(&Clock, Option, &ClockId) + Send + 'static, + >( clock: *mut ffi::GstClock, time: ffi::GstClockTime, id: gpointer, @@ -262,7 +272,9 @@ impl PeriodicClockId { glib::ffi::GTRUE } - unsafe extern "C" fn destroy_notify( + unsafe extern "C" fn destroy_notify< + F: Fn(&Clock, Option, &ClockId) + Send + 'static, + >( ptr: gpointer, ) { Box::::from_raw(ptr as *mut _); @@ -283,7 +295,7 @@ impl PeriodicClockId { pub fn wait_async_stream( &self, ) -> Result< - Pin + Unpin + Send + 'static>>, + Pin, ClockId)> + Unpin + Send + 'static>>, ClockError, > { use futures_channel::mpsc; @@ -348,7 +360,7 @@ impl Clock { cexternal: ClockTime, cnum: ClockTime, cdenom: ClockTime, - ) -> ClockTime { + ) -> Option { skip_assert_initialized!(); unsafe { from_glib(ffi::gst_clock_adjust_with_calibration( @@ -369,7 +381,7 @@ impl Clock { cexternal: ClockTime, cnum: ClockTime, cdenom: ClockTime, - ) -> ClockTime { + ) -> Option { skip_assert_initialized!(); unsafe { from_glib(ffi::gst_clock_unadjust_with_calibration( @@ -416,9 +428,7 @@ pub trait ClockExtManual: 'static { impl> ClockExtManual for O { fn new_periodic_id(&self, start_time: ClockTime, interval: ClockTime) -> PeriodicClockId { - assert!(start_time.is_some()); - assert!(interval.is_some()); - assert_ne!(interval, crate::ClockTime::from(0)); + assert_ne!(interval, ClockTime::ZERO); unsafe { PeriodicClockId(from_glib_full(ffi::gst_clock_new_periodic_id( @@ -452,8 +462,6 @@ impl> ClockExtManual for O { } fn new_single_shot_id(&self, time: ClockTime) -> SingleShotClockId { - assert!(time.is_some()); - unsafe { SingleShotClockId(from_glib_full(ffi::gst_clock_new_single_shot_id( self.as_ref().to_glib_none().0, @@ -518,8 +526,8 @@ mod tests { crate::init().unwrap(); let clock = SystemClock::obtain(); - let now = clock.time(); - let id = clock.new_single_shot_id(now + 20 * crate::MSECOND); + let now = clock.time().unwrap(); + let id = clock.new_single_shot_id(now + 20 * ClockTime::MSECOND); let (res, _) = id.wait(); assert!(res == Ok(ClockSuccess::Ok) || res == Err(ClockError::Early)); @@ -532,8 +540,8 @@ mod tests { let (sender, receiver) = channel(); let clock = SystemClock::obtain(); - let now = clock.time(); - let id = clock.new_single_shot_id(now + 20 * crate::MSECOND); + let now = clock.time().unwrap(); + let id = clock.new_single_shot_id(now + 20 * ClockTime::MSECOND); let res = id.wait_async(move |_, _, _| { sender.send(()).unwrap(); }); @@ -548,8 +556,8 @@ mod tests { crate::init().unwrap(); let clock = SystemClock::obtain(); - let now = clock.time(); - let id = clock.new_periodic_id(now + 20 * crate::MSECOND, 20 * crate::MSECOND); + let now = clock.time().unwrap(); + let id = clock.new_periodic_id(now + 20 * ClockTime::MSECOND, 20 * ClockTime::MSECOND); let (res, _) = id.wait(); assert!(res == Ok(ClockSuccess::Ok) || res == Err(ClockError::Early)); @@ -565,8 +573,8 @@ mod tests { let (sender, receiver) = channel(); let clock = SystemClock::obtain(); - let now = clock.time(); - let id = clock.new_periodic_id(now + 20 * crate::MSECOND, 20 * crate::MSECOND); + let now = clock.time().unwrap(); + let id = clock.new_periodic_id(now + 20 * ClockTime::MSECOND, 20 * ClockTime::MSECOND); let res = id.wait_async(move |_, _, _| { let _ = sender.send(()); }); diff --git a/gstreamer/src/clock_time.rs b/gstreamer/src/clock_time.rs index 4e55b7a2a..d6c598412 100644 --- a/gstreamer/src/clock_time.rs +++ b/gstreamer/src/clock_time.rs @@ -7,131 +7,265 @@ use std::io::{self, prelude::*}; use std::time::Duration; use std::{cmp, convert, fmt, str}; -#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug, Default)] -pub struct ClockTime(pub Option); +#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Debug, Default)] +pub struct ClockTime(pub(crate) u64); impl ClockTime { - pub fn hours(&self) -> Option { - (*self / crate::SECOND / 60 / 60).0 + pub const SECOND: ClockTime = ClockTime(1_000_000_000); + pub const MSECOND: ClockTime = ClockTime(1_000_000); + pub const USECOND: ClockTime = ClockTime(1_000); + pub const NSECOND: ClockTime = ClockTime(1); + + pub const fn hours(self) -> u64 { + self.0 / Self::SECOND.0 / 60 / 60 } - pub fn minutes(&self) -> Option { - (*self / crate::SECOND / 60).0 + pub const fn minutes(self) -> u64 { + self.0 / Self::SECOND.0 / 60 } - pub fn seconds(&self) -> Option { - (*self / crate::SECOND).0 + pub const fn seconds(self) -> u64 { + self.0 / Self::SECOND.0 } - pub fn mseconds(&self) -> Option { - (*self / crate::MSECOND).0 + pub const fn mseconds(self) -> u64 { + self.0 / Self::MSECOND.0 } - pub fn useconds(&self) -> Option { - (*self / crate::USECOND).0 + pub const fn useconds(self) -> u64 { + self.0 / Self::USECOND.0 } - pub fn nseconds(&self) -> Option { - (*self / crate::NSECOND).0 - } - - pub fn nanoseconds(&self) -> Option { + pub const fn nseconds(self) -> u64 { self.0 } - pub fn from_seconds(seconds: u64) -> ClockTime { + pub const fn from_seconds(seconds: u64) -> Self { skip_assert_initialized!(); - seconds * crate::SECOND + ClockTime(seconds * Self::SECOND.0) } - pub fn from_mseconds(mseconds: u64) -> ClockTime { + pub const fn from_mseconds(mseconds: u64) -> Self { skip_assert_initialized!(); - mseconds * crate::MSECOND + ClockTime(mseconds * Self::MSECOND.0) } - pub fn from_useconds(useconds: u64) -> ClockTime { + pub const fn from_useconds(useconds: u64) -> Self { skip_assert_initialized!(); - useconds * crate::USECOND + ClockTime(useconds * Self::USECOND.0) } - pub fn from_nseconds(nseconds: u64) -> ClockTime { + pub const fn from_nseconds(nseconds: u64) -> Self { skip_assert_initialized!(); - nseconds * crate::NSECOND + ClockTime(nseconds * Self::NSECOND.0) } } -// This macro is also used by formats with an inner Option. -// It is defined here because the format module depends on ClockTime. -macro_rules! impl_common_ops_for_opt_int( - ($name:ident) => { - impl $name { - #[must_use = "this returns the result of the operation, without modifying the original"] - #[inline] - pub fn saturating_add(self, rhs: Self) -> Option { - match (self.0, rhs.0) { - (Some(this), Some(rhs)) => Some(Self(Some(this.saturating_add(rhs)))), - _ => None, - } - } +macro_rules! option_glib_newtype_from_to { + ($type_:ident, $none_value:expr) => { + #[doc(hidden)] + impl IntoGlib for $type_ { + type GlibType = u64; - #[must_use = "this returns the result of the operation, without modifying the original"] - #[inline] - pub fn saturating_sub(self, rhs: Self) -> Option { - match (self.0, rhs.0) { - (Some(this), Some(rhs)) => Some(Self(Some(this.saturating_sub(rhs)))), - _ => None, - } - } - - #[must_use = "this returns the result of the operation, without modifying the original"] - #[inline] - pub fn min(self, rhs: Self) -> Option { - match (self.0, rhs.0) { - (Some(this), Some(rhs)) => Some(Self(Some(this.min(rhs)))), - _ => None, - } - } - - #[must_use = "this returns the result of the operation, without modifying the original"] - #[inline] - pub fn max(self, rhs: Self) -> Option { - match (self.0, rhs.0) { - (Some(this), Some(rhs)) => Some(Self(Some(this.max(rhs)))), - _ => None, - } - } - - pub const fn zero() -> Self { - Self(Some(0)) - } - - pub fn is_zero(&self) -> bool { - matches!(self.0, Some(0)) - } - - pub const fn none() -> Self { - Self(None) + fn into_glib(self) -> u64 { + self.0 } } - impl cmp::PartialOrd for $name { - fn partial_cmp(&self, other: &Self) -> Option { - match (self.0, other.0) { - (Some(this), Some(other)) => this.partial_cmp(&other), - (None, None) => Some(cmp::Ordering::Equal), - _ => None, + #[doc(hidden)] + impl OptionIntoGlib for $type_ { + const GLIB_NONE: u64 = $none_value; + } + + #[doc(hidden)] + impl TryFromGlib for $type_ { + type Error = GlibNoneError; + #[inline] + unsafe fn try_from_glib(val: u64) -> Result { + skip_assert_initialized!(); + if val == $none_value { + return Err(GlibNoneError); } + + Ok($type_(val)) + } + } + }; +} + +option_glib_newtype_from_to!(ClockTime, ffi::GST_CLOCK_TIME_NONE); + +impl glib::value::ValueType for ClockTime { + type Type = Self; +} + +pub struct ClockTimeValueTypeOrNoneChecker(std::marker::PhantomData); + +unsafe impl glib::value::ValueTypeChecker for ClockTimeValueTypeOrNoneChecker { + type Error = glib::value::ValueTypeMismatchOrNoneError; + + fn check(value: &glib::Value) -> Result<(), Self::Error> { + skip_assert_initialized!(); + glib::value::GenericValueTypeChecker::::check(value)?; + + let gct = unsafe { glib::gobject_ffi::g_value_get_uint64(value.to_glib_none().0) }; + if gct == ffi::GST_CLOCK_TIME_NONE { + return Err(glib::value::ValueTypeMismatchOrNoneError::UnexpectedNone); + } + + Ok(()) + } +} + +unsafe impl<'a> glib::value::FromValue<'a> for ClockTime { + type Checker = ClockTimeValueTypeOrNoneChecker; + + unsafe fn from_value(value: &glib::Value) -> ClockTime { + skip_assert_initialized!(); + ClockTime(glib::gobject_ffi::g_value_get_uint64( + value.to_glib_none().0, + )) + } +} + +impl glib::value::ToValue for ClockTime { + fn to_value(&self) -> glib::Value { + let mut value = glib::Value::for_value_type::(); + let gct = self.into_glib(); + if gct == ffi::GST_CLOCK_TIME_NONE { + crate::gst_warning!( + crate::CAT_RUST, + "converting a defined `ClockTime` with value `ffi::GST_CLOCK_TIME_NONE` to `Value`, this is probably not what you wanted.", + ); + } + unsafe { glib::gobject_ffi::g_value_set_uint64(value.to_glib_none_mut().0, gct) } + value + } + + fn value_type(&self) -> glib::Type { + Self::static_type() + } +} + +impl glib::value::ToValueOptional for ClockTime { + fn to_value_optional(opt: Option<&Self>) -> glib::Value { + skip_assert_initialized!(); + let mut value = glib::Value::for_value_type::(); + let inner = opt.map(|inner| inner.0).unwrap_or(ffi::GST_CLOCK_TIME_NONE); + unsafe { glib::gobject_ffi::g_value_set_uint64(value.to_glib_none_mut().0, inner) }; + + value + } +} + +#[doc(hidden)] +impl glib::StaticType for ClockTime { + fn static_type() -> glib::Type { + ::static_type() + } +} + +#[derive(Debug)] +pub struct DurationError; + +impl fmt::Display for DurationError { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(fmt, "out of range conversion from Duration attempted") + } +} + +impl std::error::Error for DurationError {} + +impl convert::TryFrom for ClockTime { + type Error = DurationError; + + fn try_from(d: Duration) -> Result { + skip_assert_initialized!(); + + let nanos = d.as_nanos(); + + // Note: `std::u64::MAX` is `ClockTime::None`. + if nanos >= std::u64::MAX as u128 { + return Err(DurationError); + } + + Ok(ClockTime::from_nseconds(nanos as u64)) + } +} + +impl convert::From for Duration { + fn from(t: ClockTime) -> Self { + skip_assert_initialized!(); + + Duration::from_nanos(t.nseconds()) + } +} + +macro_rules! impl_common_ops_for_newtype_u64( + ($name:ident) => { + impl $name { + pub const ZERO: Self = Self(0); + pub const NONE: Option = None; + + pub const fn is_zero(self) -> bool { + self.0 == Self::ZERO.0 + } + + #[must_use = "this returns the result of the operation, without modifying the original"] + #[inline] + // FIXME Can't use `map` in a `const fn` as of rustc 1.53.0-beta.2 + #[allow(clippy::manual_map)] + pub const fn checked_add(self, rhs: Self) -> Option { + match self.0.checked_add(rhs.0) { + Some(res) => Some(Self(res)), + None => None, + } + } + + #[must_use = "this returns the result of the operation, without modifying the original"] + #[inline] + pub const fn saturating_add(self, rhs: Self) -> Self { + Self(self.0.saturating_add(rhs.0)) + } + + #[must_use = "this returns the result of the operation, without modifying the original"] + #[inline] + pub const fn wrapping_add(self, rhs: Self) -> Self { + Self(self.0.wrapping_add(rhs.0)) + } + + #[must_use = "this returns the result of the operation, without modifying the original"] + #[inline] + // FIXME Can't use `map` in a `const fn` as of rustc 1.53.0-beta.2 + #[allow(clippy::manual_map)] + pub const fn checked_sub(self, rhs: Self) -> Option { + match self.0.checked_sub(rhs.0) { + Some(res) => Some(Self(res)), + None => None, + } + } + + #[must_use = "this returns the result of the operation, without modifying the original"] + #[inline] + pub const fn saturating_sub(self, rhs: Self) -> Self { + Self(self.0.saturating_sub(rhs.0)) + } + + #[must_use = "this returns the result of the operation, without modifying the original"] + #[inline] + pub const fn wrapping_sub(self, rhs: Self) -> Self { + Self(self.0.wrapping_sub(rhs.0)) } } }; ); -impl_common_ops_for_opt_int!(ClockTime); +impl_common_ops_for_newtype_u64!(ClockTime); /// Tell [`pad_clocktime`] what kind of time we're formatting enum Sign { - /// An invalid time (`None`) - Invalid, + /// An undefined time (`None`) + Undefined, /// A non-negative time (zero or greater) NonNegative, @@ -161,18 +295,18 @@ fn pad_clocktime(f: &mut fmt::Formatter<'_>, sign: Sign, buf: &str) -> fmt::Resu // Choose the fill character let sign_aware_zero_pad = f.sign_aware_zero_pad(); let fill_char = match sign { - Invalid if sign_aware_zero_pad => '-', // Zero-padding an invalid time - _ if sign_aware_zero_pad => '0', // Zero-padding a valid time - _ => f.fill(), // Otherwise, pad with the user-chosen character + Undefined if sign_aware_zero_pad => '-', // Zero-padding an undefined time + _ if sign_aware_zero_pad => '0', // Zero-padding a valid time + _ => f.fill(), // Otherwise, pad with the user-chosen character }; // Choose the sign character let sign_plus = f.sign_plus(); let sign_char = match sign { - Invalid if sign_plus => Some(fill_char), // User requested sign, time is invalid - NonNegative if sign_plus => Some('+'), // User requested sign, time is zero or above - Negative => Some('-'), // Time is below zero - _ => None, // Otherwise, add no sign + Undefined if sign_plus => Some(fill_char), // User requested sign, time is undefined + NonNegative if sign_plus => Some('+'), // User requested sign, time is zero or above + Negative => Some('-'), // Time is below zero + _ => None, // Otherwise, add no sign }; // Our minimum width is the value's width, plus 1 for the sign if present @@ -216,15 +350,13 @@ fn pad_clocktime(f: &mut fmt::Formatter<'_>, sign: Sign, buf: &str) -> fmt::Resu /// Writes an unpadded, signless clocktime string with the given precision fn write_clocktime( mut writer: W, - clocktime: Option, + clocktime: Option, precision: usize, ) -> io::Result<()> { skip_assert_initialized!(); let precision = cmp::min(9, precision); - if let Some(ns) = clocktime { - // Valid time - + if let Some(ns) = clocktime.map(ClockTime::nseconds) { // Split the time into parts let (s, ns) = div_rem(ns, 1_000_000_000); let (m, s) = div_rem(s, 60); @@ -244,7 +376,7 @@ fn write_clocktime( write!(writer, ".{:.p$}", buf_str, p = precision)?; } } else { - // Invalid time + // Undefined time // Write HH:MM:SS, but invalid write!(writer, "--:--:--")?; @@ -258,114 +390,57 @@ fn write_clocktime( Ok(()) } +fn fmt_opt_clock_time(ct: Option, f: &mut fmt::Formatter) -> fmt::Result { + skip_assert_initialized!(); + let precision = f.precision().unwrap_or(9); + + // What the maximum time (u64::MAX - 1) would format to + const MAX_SIZE: usize = "5124095:34:33.709551614".len(); + + // Write the unpadded clocktime value into a stack-allocated string + let mut buf = [0u8; MAX_SIZE]; + let mut cursor = io::Cursor::new(&mut buf[..]); + write_clocktime(&mut cursor, ct, precision).unwrap(); + let pos = cursor.position() as usize; + let buf_str = str::from_utf8(&buf[..pos]).unwrap(); + + let sign = if ct.is_some() { + Sign::NonNegative + } else { + Sign::Undefined + }; + + pad_clocktime(f, sign, buf_str) +} + impl fmt::Display for ClockTime { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let precision = f.precision().unwrap_or(9); - - // What the maximum time (u64::MAX - 1) would format to - const MAX_SIZE: usize = "5124095:34:33.709551614".len(); - - // Write the unpadded clocktime value into a stack-allocated string - let mut buf = [0u8; MAX_SIZE]; - let mut cursor = io::Cursor::new(&mut buf[..]); - write_clocktime(&mut cursor, self.0, precision).unwrap(); - let pos = cursor.position() as usize; - let buf_str = str::from_utf8(&buf[..pos]).unwrap(); - - let sign = if self.0.is_some() { - Sign::NonNegative - } else { - Sign::Invalid - }; - - pad_clocktime(f, sign, buf_str) + fmt_opt_clock_time(Some(*self), f) } } -#[doc(hidden)] -impl IntoGlib for ClockTime { - type GlibType = ffi::GstClockTime; +#[derive(Debug)] +pub struct DisplayableOptClockTime(Option); - fn into_glib(self) -> ffi::GstClockTime { - match self.0 { - None => ffi::GST_CLOCK_TIME_NONE, - Some(v) => v, - } +impl fmt::Display for DisplayableOptClockTime { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt_opt_clock_time(self.0, f) } } -#[doc(hidden)] -impl FromGlib for ClockTime { - unsafe fn from_glib(value: ffi::GstClockTime) -> Self { - skip_assert_initialized!(); - match value { - ffi::GST_CLOCK_TIME_NONE => ClockTime(None), - value => ClockTime(Some(value)), - } +impl crate::utils::Displayable for Option { + type DisplayImpl = DisplayableOptClockTime; + + fn display(self) -> DisplayableOptClockTime { + DisplayableOptClockTime(self) } } -impl glib::value::ValueType for ClockTime { - type Type = Self; -} +impl crate::utils::Displayable for ClockTime { + type DisplayImpl = ClockTime; -#[doc(hidden)] -unsafe impl<'a> glib::value::FromValue<'a> for ClockTime { - type Checker = glib::value::GenericValueTypeChecker; - - unsafe fn from_value(value: &glib::Value) -> Self { - skip_assert_initialized!(); - from_glib(glib::gobject_ffi::g_value_get_uint64( - value.to_glib_none().0, - )) - } -} - -#[doc(hidden)] -impl glib::value::ToValue for ClockTime { - fn to_value(&self) -> glib::Value { - let mut value = glib::Value::for_value_type::(); - unsafe { - glib::gobject_ffi::g_value_set_uint64(value.to_glib_none_mut().0, self.into_glib()) - } - value - } - - fn value_type(&self) -> glib::Type { - Self::static_type() - } -} - -#[doc(hidden)] -impl glib::StaticType for ClockTime { - fn static_type() -> glib::Type { - ::static_type() - } -} - -impl From for ClockTime { - fn from(d: Duration) -> Self { - skip_assert_initialized!(); - - let nanos = d.as_nanos(); - - if nanos > std::u64::MAX as u128 { - crate::CLOCK_TIME_NONE - } else { - ClockTime::from_nseconds(nanos as u64) - } - } -} - -impl convert::TryFrom for Duration { - type Error = glib::BoolError; - - fn try_from(t: ClockTime) -> Result { - skip_assert_initialized!(); - - t.nanoseconds() - .map(Duration::from_nanos) - .ok_or_else(|| glib::bool_error!("Can't convert ClockTime::NONE to Duration")) + fn display(self) -> ClockTime { + self } } @@ -374,188 +449,184 @@ mod tests { use super::*; #[test] - #[allow(clippy::eq_op)] - fn ops() { - let ct_10 = ClockTime::from_mseconds(10); - let ct_20 = ClockTime::from_mseconds(20); - let ct_30 = ClockTime::from_mseconds(30); + fn opt_time_clock() { + let ct_1 = ClockTime(1); + let opt_ct_none: Option = None; - let ct_none = ClockTime::none(); + assert_eq!(ct_1.into_glib(), 1); + assert_eq!(Some(ct_1).into_glib(), 1); + assert_eq!(opt_ct_none.into_glib(), ffi::GST_CLOCK_TIME_NONE); + + let ct_1_from: ClockTime = unsafe { try_from_glib(1u64) }.unwrap(); + assert_eq!(ct_1_from, ct_1); + + let opt_ct_some: Option = unsafe { from_glib(1u64) }; + assert_eq!(opt_ct_some, Some(ct_1)); + + let opt_ct_none: Option = unsafe { from_glib(ffi::GST_CLOCK_TIME_NONE) }; + assert_eq!(opt_ct_none, None); + } + + #[test] + #[allow(clippy::eq_op, clippy::op_ref)] + fn ops() { + let ct_10 = 10 * ClockTime::MSECOND; + let ct_20 = 20 * ClockTime::MSECOND; + let ct_30 = 30 * ClockTime::MSECOND; assert_eq!(ct_10 + ct_20, ct_30); - assert_eq!(ct_10 + ct_none, ct_none); - assert_eq!(ct_none + ct_10, ct_none); - assert_eq!(ct_none + ct_none, ct_none); - + assert_eq!(ct_10 + &ct_20, ct_30); + assert_eq!(&ct_10 + &ct_20, ct_30); assert_eq!(ct_30 - ct_20, ct_10); - assert_eq!(ct_30 - ct_30, ClockTime::zero()); - assert_eq!(ct_30 - ct_none, ct_none); - assert_eq!(ct_none - ct_30, ct_none); - assert_eq!(ct_none - ct_none, ct_none); + assert_eq!(ct_30 - ct_30, ClockTime::ZERO); + assert_eq!(ct_10 * 3, ct_30); + assert_eq!(3 * ct_10, ct_30); + assert_eq!(3 * &ct_10, ct_30); + assert_eq!(ct_30.nseconds(), 30_000_000); + } + + #[test] + fn checked_ops() { + let ct_1 = ClockTime::from_nseconds(1); + let ct_2 = ClockTime::from_nseconds(2); + + let ct_max = ClockTime::from_nseconds(std::u64::MAX); + + assert_eq!(ct_1.checked_add(ct_1), Some(ct_2)); + assert_eq!(ct_1.checked_add(ct_1), Some(ct_2)); + assert!(ct_max.checked_add(ct_1).is_none()); + + assert_eq!(ct_2.checked_sub(ct_1), Some(ct_1)); + assert_eq!(ct_2.checked_sub(ct_1), Some(ct_1)); + assert!(ct_1.checked_sub(ct_2).is_none()); } #[test] fn saturating_ops() { let ct_1 = ClockTime::from_nseconds(1); let ct_2 = ClockTime::from_nseconds(2); + let ct_3 = ClockTime::from_nseconds(3); let ct_max = ClockTime::from_nseconds(std::u64::MAX); - let ct_none = ClockTime::none(); - assert_eq!(ct_max.saturating_add(ct_1), Some(ct_max)); - assert!(ct_max.saturating_add(ct_none).is_none()); - assert!(ct_none.saturating_add(ct_max).is_none()); + assert_eq!(ct_1.saturating_add(ct_2), ct_3); + assert_eq!(ct_1.saturating_add(ct_2), ct_3); + assert_eq!(ct_max.saturating_add(ct_1), ct_max); - assert!(ct_1.saturating_sub(ct_2).unwrap().is_zero()); - assert!(ct_1.saturating_sub(ct_none).is_none()); - assert!(ct_none.saturating_sub(ct_1).is_none()); + assert_eq!(ct_3.saturating_sub(ct_2), ct_1); + assert_eq!(ct_3.saturating_sub(ct_2), ct_1); + assert!(ct_1.saturating_sub(ct_2).is_zero()); } #[test] - #[allow(clippy::eq_op)] - fn eq() { - let ct_10 = ClockTime::from_mseconds(10); - let ct_10_2 = ClockTime::from_mseconds(10); - let ct_10_3 = ClockTime::from_mseconds(10); - let ct_20 = ClockTime::from_mseconds(20); + fn wrapping_ops() { + let ct_1 = ClockTime::NSECOND; + let ct_2 = 2 * ClockTime::NSECOND; + let ct_3 = 3 * ClockTime::NSECOND; - let ct_none = ClockTime::none(); - let ct_none_2 = ClockTime::none(); - let ct_none_3 = ClockTime::none(); + let ct_max = ClockTime::from_nseconds(std::u64::MAX); - // ## Eq + assert_eq!(ct_1.wrapping_add(ct_2), ct_3); + assert_eq!(ct_1.wrapping_add(ct_2), ct_3); + assert_eq!(ct_max.wrapping_add(ct_1), ClockTime::ZERO); - // ### (a == b) and (a != b) are strict inverses - assert!(ct_10 == ct_10_2); - assert_ne!(ct_10 == ct_10_2, ct_10 != ct_10_2); - - assert!(ct_10 != ct_20); - assert_ne!(ct_10 == ct_20, ct_10 != ct_20); - - assert!(ct_none == ct_none_2); - assert_ne!(ct_none == ct_none_2, ct_none != ct_none_2); - - assert!(ct_10 != ct_none); - assert_ne!(ct_10 == ct_none, ct_10 != ct_none); - - assert!(ct_none != ct_10); - assert_ne!(ct_none == ct_10, ct_none != ct_10); - - // ### Reflexivity (a == a) - assert!(ct_10 == ct_10); - assert!(ct_none == ct_none); - - // ## PartialEq - - // ### Symmetric (a == b) => (b == a) - assert!((ct_10 == ct_10_2) && (ct_10_2 == ct_10)); - assert!((ct_none == ct_none_2) && (ct_none_2 == ct_none)); - - // ### Transitive (a == b) and (b == c) => (a == c) - assert!((ct_10 == ct_10_2) && (ct_10_2 == ct_10_3) && (ct_10 == ct_10_3)); - assert!((ct_none == ct_none_2) && (ct_none_2 == ct_none_3) && (ct_none == ct_none_3)); + assert_eq!(ct_3.wrapping_sub(ct_2), ct_1); + assert_eq!(ct_3.wrapping_sub(ct_2), ct_1); + assert_eq!(ct_1.wrapping_sub(ct_2), ct_max); } #[test] - #[allow(clippy::neg_cmp_op_on_partial_ord)] - fn partial_ord() { - let ct_10 = ClockTime::from_mseconds(10); - let ct_20 = ClockTime::from_mseconds(20); - let ct_30 = ClockTime::from_mseconds(30); + fn comp() { + let ct_0 = ClockTime::ZERO; + let ct_2 = 2 * ClockTime::NSECOND; + let ct_3 = 3 * ClockTime::NSECOND; + let opt_ct_none: Option = None; - let ct_none = ClockTime::none(); + assert!(ct_0 < ct_2); + assert!(Some(ct_0) < Some(ct_2)); + assert!(ct_2 < ct_3); + assert!(Some(ct_2) < Some(ct_3)); + assert!(ct_0 < ct_3); + assert!(Some(ct_0) < Some(ct_3)); - // Special cases - assert_eq!(ct_10 < ct_none, false); - assert_eq!(ct_10 > ct_none, false); - assert_eq!(ct_none < ct_10, false); - assert_eq!(ct_none > ct_10, false); + assert!(ct_3 > ct_2); + assert!(Some(ct_3) > Some(ct_2)); + assert!(ct_2 > ct_0); + assert!(Some(ct_2) > Some(ct_0)); + assert!(ct_3 > ct_0); + assert!(Some(ct_3) > Some(ct_0)); - // Asymmetric a < b => !(a > b) - // a < b => !(a > b) - assert!((ct_10 < ct_20) && !(ct_10 > ct_20)); - // a > b => !(a < b) - assert!((ct_20 > ct_10) && !(ct_20 < ct_10)); - - // Transitive - // a < b and b < c => a < c - assert!((ct_10 < ct_20) && (ct_20 < ct_30) && (ct_10 < ct_30)); - // a > b and b > c => a > c - assert!((ct_30 > ct_20) && (ct_20 > ct_10) && (ct_30 > ct_10)); - } - - #[test] - fn not_ord() { - let ct_10 = ClockTime::from_mseconds(10); - let ct_20 = ClockTime::from_mseconds(20); - let ct_none = ClockTime::none(); - - // Total & Antisymmetric exactly one of a < b, a == b or a > b is true - - assert!((ct_10 < ct_20) ^ (ct_10 == ct_20) ^ (ct_10 > ct_20)); - - // Not Ord due to: - assert_eq!( - (ct_10 < ct_none) ^ (ct_10 == ct_none) ^ (ct_10 > ct_none), - false - ); - assert_eq!( - (ct_none < ct_10) ^ (ct_none == ct_10) ^ (ct_none > ct_10), - false - ); - } - - #[test] - fn min_max() { - let ct_10 = ClockTime::from_nseconds(10); - let ct_20 = ClockTime::from_nseconds(20); - let ct_none = ClockTime::none(); - - assert_eq!(ct_10.min(ct_20).unwrap(), ct_10); - assert_eq!(ct_20.min(ct_10).unwrap(), ct_10); - assert!(ct_none.min(ct_10).is_none()); - assert!(ct_20.min(ct_none).is_none()); - - assert_eq!(ct_10.max(ct_20).unwrap(), ct_20); - assert_eq!(ct_20.max(ct_10).unwrap(), ct_20); - assert!(ct_none.max(ct_10).is_none()); - assert!(ct_20.max(ct_none).is_none()); + assert_eq!(opt_ct_none < None, false); + assert_eq!(opt_ct_none > None, false); + // This doesn't work due to the `PartialOrd` impl on `Option` + //assert_eq!(Some(ct_0) > opt_ct_none, false); + assert_eq!(Some(ct_0) < opt_ct_none, false); } #[test] fn display() { - let none = ClockTime::none(); - let some = ClockTime::from_nseconds(45834908569837); + let none = Option::::None; + let some = Some(45_834_908_569_837 * ClockTime::NSECOND); let lots = ClockTime::from_nseconds(std::u64::MAX - 1); // Simple - assert_eq!(format!("{:.0}", none), "--:--:--"); - assert_eq!(format!("{:.3}", none), "--:--:--.---"); - assert_eq!(format!("{}", none), "--:--:--.---------"); + assert_eq!(format!("{:.0}", DisplayableOptClockTime(none)), "--:--:--"); + assert_eq!( + format!("{:.3}", DisplayableOptClockTime(none)), + "--:--:--.---" + ); + assert_eq!( + format!("{}", DisplayableOptClockTime(none)), + "--:--:--.---------" + ); - assert_eq!(format!("{:.0}", some), "12:43:54"); - assert_eq!(format!("{:.3}", some), "12:43:54.908"); - assert_eq!(format!("{}", some), "12:43:54.908569837"); + assert_eq!(format!("{:.0}", DisplayableOptClockTime(some)), "12:43:54"); + assert_eq!( + format!("{:.3}", DisplayableOptClockTime(some)), + "12:43:54.908" + ); + assert_eq!( + format!("{}", DisplayableOptClockTime(some)), + "12:43:54.908569837" + ); assert_eq!(format!("{:.0}", lots), "5124095:34:33"); assert_eq!(format!("{:.3}", lots), "5124095:34:33.709"); assert_eq!(format!("{}", lots), "5124095:34:33.709551614"); // Precision caps at 9 - assert_eq!(format!("{:.10}", none), "--:--:--.---------"); - assert_eq!(format!("{:.10}", some), "12:43:54.908569837"); + assert_eq!( + format!("{:.10}", DisplayableOptClockTime(none)), + "--:--:--.---------" + ); + assert_eq!( + format!("{:.10}", DisplayableOptClockTime(some)), + "12:43:54.908569837" + ); assert_eq!(format!("{:.10}", lots), "5124095:34:33.709551614"); // Short width - assert_eq!(format!("{:4.0}", none), "--:--:--"); - assert_eq!(format!("{:4.3}", none), "--:--:--.---"); - assert_eq!(format!("{:4}", none), "--:--:--.---------"); + assert_eq!(format!("{:4.0}", DisplayableOptClockTime(none)), "--:--:--"); + assert_eq!( + format!("{:4.3}", DisplayableOptClockTime(none)), + "--:--:--.---" + ); + assert_eq!( + format!("{:4}", DisplayableOptClockTime(none)), + "--:--:--.---------" + ); - assert_eq!(format!("{:4.0}", some), "12:43:54"); - assert_eq!(format!("{:4.3}", some), "12:43:54.908"); - assert_eq!(format!("{:4}", some), "12:43:54.908569837"); + assert_eq!(format!("{:4.0}", DisplayableOptClockTime(some)), "12:43:54"); + assert_eq!( + format!("{:4.3}", DisplayableOptClockTime(some)), + "12:43:54.908" + ); + assert_eq!( + format!("{:4}", DisplayableOptClockTime(some)), + "12:43:54.908569837" + ); assert_eq!(format!("{:4.0}", lots), "5124095:34:33"); assert_eq!(format!("{:4.3}", lots), "5124095:34:33.709"); @@ -563,25 +634,79 @@ mod tests { // Simple padding - assert_eq!(format!("{:>9.0}", none), " --:--:--"); - assert_eq!(format!("{:<9.0}", none), "--:--:-- "); - assert_eq!(format!("{:^10.0}", none), " --:--:-- "); - assert_eq!(format!("{:>13.3}", none), " --:--:--.---"); - assert_eq!(format!("{:<13.3}", none), "--:--:--.--- "); - assert_eq!(format!("{:^14.3}", none), " --:--:--.--- "); - assert_eq!(format!("{:>19}", none), " --:--:--.---------"); - assert_eq!(format!("{:<19}", none), "--:--:--.--------- "); - assert_eq!(format!("{:^20}", none), " --:--:--.--------- "); + assert_eq!( + format!("{:>9.0}", DisplayableOptClockTime(none)), + " --:--:--" + ); + assert_eq!( + format!("{:<9.0}", DisplayableOptClockTime(none)), + "--:--:-- " + ); + assert_eq!( + format!("{:^10.0}", DisplayableOptClockTime(none)), + " --:--:-- " + ); + assert_eq!( + format!("{:>13.3}", DisplayableOptClockTime(none)), + " --:--:--.---" + ); + assert_eq!( + format!("{:<13.3}", DisplayableOptClockTime(none)), + "--:--:--.--- " + ); + assert_eq!( + format!("{:^14.3}", DisplayableOptClockTime(none)), + " --:--:--.--- " + ); + assert_eq!( + format!("{:>19}", DisplayableOptClockTime(none)), + " --:--:--.---------" + ); + assert_eq!( + format!("{:<19}", DisplayableOptClockTime(none)), + "--:--:--.--------- " + ); + assert_eq!( + format!("{:^20}", DisplayableOptClockTime(none)), + " --:--:--.--------- " + ); - assert_eq!(format!("{:>9.0}", some), " 12:43:54"); - assert_eq!(format!("{:<9.0}", some), "12:43:54 "); - assert_eq!(format!("{:^10.0}", some), " 12:43:54 "); - assert_eq!(format!("{:>13.3}", some), " 12:43:54.908"); - assert_eq!(format!("{:<13.3}", some), "12:43:54.908 "); - assert_eq!(format!("{:^14.3}", some), " 12:43:54.908 "); - assert_eq!(format!("{:>19}", some), " 12:43:54.908569837"); - assert_eq!(format!("{:<19}", some), "12:43:54.908569837 "); - assert_eq!(format!("{:^20}", some), " 12:43:54.908569837 "); + assert_eq!( + format!("{:>9.0}", DisplayableOptClockTime(some)), + " 12:43:54" + ); + assert_eq!( + format!("{:<9.0}", DisplayableOptClockTime(some)), + "12:43:54 " + ); + assert_eq!( + format!("{:^10.0}", DisplayableOptClockTime(some)), + " 12:43:54 " + ); + assert_eq!( + format!("{:>13.3}", DisplayableOptClockTime(some)), + " 12:43:54.908" + ); + assert_eq!( + format!("{:<13.3}", DisplayableOptClockTime(some)), + "12:43:54.908 " + ); + assert_eq!( + format!("{:^14.3}", DisplayableOptClockTime(some)), + " 12:43:54.908 " + ); + assert_eq!( + format!("{:>19}", DisplayableOptClockTime(some)), + " 12:43:54.908569837" + ); + assert_eq!( + format!("{:<19}", DisplayableOptClockTime(some)), + "12:43:54.908569837 " + ); + assert_eq!( + format!("{:^20}", DisplayableOptClockTime(some)), + " 12:43:54.908569837 " + ); assert_eq!(format!("{:>14.0}", lots), " 5124095:34:33"); assert_eq!(format!("{:<14.0}", lots), "5124095:34:33 "); @@ -595,25 +720,79 @@ mod tests { // Padding with sign or zero-extension - assert_eq!(format!("{:+11.0}", none), " --:--:--"); - assert_eq!(format!("{:011.0}", none), "-----:--:--"); - assert_eq!(format!("{:+011.0}", none), "-----:--:--"); - assert_eq!(format!("{:+15.3}", none), " --:--:--.---"); - assert_eq!(format!("{:015.3}", none), "-----:--:--.---"); - assert_eq!(format!("{:+015.3}", none), "-----:--:--.---"); - assert_eq!(format!("{:+21}", none), " --:--:--.---------"); - assert_eq!(format!("{:021}", none), "-----:--:--.---------"); - assert_eq!(format!("{:+021}", none), "-----:--:--.---------"); + assert_eq!( + format!("{:+11.0}", DisplayableOptClockTime(none)), + " --:--:--" + ); + assert_eq!( + format!("{:011.0}", DisplayableOptClockTime(none)), + "-----:--:--" + ); + assert_eq!( + format!("{:+011.0}", DisplayableOptClockTime(none)), + "-----:--:--" + ); + assert_eq!( + format!("{:+15.3}", DisplayableOptClockTime(none)), + " --:--:--.---" + ); + assert_eq!( + format!("{:015.3}", DisplayableOptClockTime(none)), + "-----:--:--.---" + ); + assert_eq!( + format!("{:+015.3}", DisplayableOptClockTime(none)), + "-----:--:--.---" + ); + assert_eq!( + format!("{:+21}", DisplayableOptClockTime(none)), + " --:--:--.---------" + ); + assert_eq!( + format!("{:021}", DisplayableOptClockTime(none)), + "-----:--:--.---------" + ); + assert_eq!( + format!("{:+021}", DisplayableOptClockTime(none)), + "-----:--:--.---------" + ); - assert_eq!(format!("{:+11.0}", some), " +12:43:54"); - assert_eq!(format!("{:011.0}", some), "00012:43:54"); - assert_eq!(format!("{:+011.0}", some), "+0012:43:54"); - assert_eq!(format!("{:+15.3}", some), " +12:43:54.908"); - assert_eq!(format!("{:015.3}", some), "00012:43:54.908"); - assert_eq!(format!("{:+015.3}", some), "+0012:43:54.908"); - assert_eq!(format!("{:+21}", some), " +12:43:54.908569837"); - assert_eq!(format!("{:021}", some), "00012:43:54.908569837"); - assert_eq!(format!("{:+021}", some), "+0012:43:54.908569837"); + assert_eq!( + format!("{:+11.0}", DisplayableOptClockTime(some)), + " +12:43:54" + ); + assert_eq!( + format!("{:011.0}", DisplayableOptClockTime(some)), + "00012:43:54" + ); + assert_eq!( + format!("{:+011.0}", DisplayableOptClockTime(some)), + "+0012:43:54" + ); + assert_eq!( + format!("{:+15.3}", DisplayableOptClockTime(some)), + " +12:43:54.908" + ); + assert_eq!( + format!("{:015.3}", DisplayableOptClockTime(some)), + "00012:43:54.908" + ); + assert_eq!( + format!("{:+015.3}", DisplayableOptClockTime(some)), + "+0012:43:54.908" + ); + assert_eq!( + format!("{:+21}", DisplayableOptClockTime(some)), + " +12:43:54.908569837" + ); + assert_eq!( + format!("{:021}", DisplayableOptClockTime(some)), + "00012:43:54.908569837" + ); + assert_eq!( + format!("{:+021}", DisplayableOptClockTime(some)), + "+0012:43:54.908569837" + ); assert_eq!(format!("{:+16.0}", lots), " +5124095:34:33"); assert_eq!(format!("{:016.0}", lots), "0005124095:34:33"); diff --git a/gstreamer/src/clock_time_serde.rs b/gstreamer/src/clock_time_serde.rs index f22e8b171..deba671f9 100644 --- a/gstreamer/src/clock_time_serde.rs +++ b/gstreamer/src/clock_time_serde.rs @@ -1,46 +1,20 @@ // Take a look at the license at the top of the repository in the LICENSE file. -use serde::de; -use serde::de::{Deserialize, Deserializer, Visitor}; +use serde::de::{Deserialize, Deserializer}; use serde::ser::{Serialize, Serializer}; -use std::fmt; - use crate::ClockTime; impl<'a> Serialize for ClockTime { fn serialize(&self, serializer: S) -> Result { - match self.nanoseconds() { - Some(ref value) => serializer.serialize_some(value), - None => serializer.serialize_none(), - } - } -} - -struct ClockTimeVisitor; -impl<'de> Visitor<'de> for ClockTimeVisitor { - type Value = ClockTime; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("an optional u64 ClockTime with ns precision") - } - - fn visit_some(self, deserializer: D) -> Result - where - D: Deserializer<'de>, - { - u64::deserialize(deserializer).map(ClockTime::from_nseconds) - } - - fn visit_none(self) -> Result { - Ok(ClockTime(None)) + self.0.serialize(serializer) } } impl<'de> Deserialize<'de> for ClockTime { fn deserialize>(deserializer: D) -> Result { skip_assert_initialized!(); - deserializer.deserialize_option(ClockTimeVisitor) + u64::deserialize(deserializer).map(ClockTime::from_nseconds) } } @@ -53,7 +27,7 @@ mod tests { crate::init().unwrap(); // Some - let clocktime = ClockTime::from_nseconds(42_123_456_789); + let clocktime = Some(ClockTime::from_nseconds(42_123_456_789)); let pretty_config = ron::ser::PrettyConfig::new().with_new_line("".to_string()); @@ -64,7 +38,7 @@ mod tests { assert_eq!("42123456789".to_owned(), res); // None - let clocktime = ClockTime(None); + let clocktime = ClockTime::NONE; let res = ron::ser::to_string_pretty(&clocktime, pretty_config); assert_eq!(Ok("None".to_owned()), res); @@ -79,46 +53,59 @@ mod tests { // Some let clocktime_ron = "Some(42123456789)"; - let clocktime: ClockTime = ron::de::from_str(clocktime_ron).unwrap(); - assert_eq!(clocktime.seconds(), Some(42)); - assert_eq!(clocktime.mseconds(), Some(42_123)); - assert_eq!(clocktime.useconds(), Some(42_123_456)); - assert_eq!(clocktime.nseconds(), Some(42_123_456_789)); + let clocktime: Option = ron::de::from_str(clocktime_ron).unwrap(); + let clocktime = clocktime.unwrap(); + assert_eq!(clocktime.seconds(), 42); + assert_eq!(clocktime.mseconds(), 42_123); + assert_eq!(clocktime.useconds(), 42_123_456); + assert_eq!(clocktime.nseconds(), 42_123_456_789); let clocktime_json = "42123456789"; - let clocktime: ClockTime = serde_json::from_str(clocktime_json).unwrap(); - assert_eq!(clocktime.seconds(), Some(42)); - assert_eq!(clocktime.mseconds(), Some(42_123)); - assert_eq!(clocktime.useconds(), Some(42_123_456)); - assert_eq!(clocktime.nseconds(), Some(42_123_456_789)); + let clocktime: Option = serde_json::from_str(clocktime_json).unwrap(); + let clocktime = clocktime.unwrap(); + assert_eq!(clocktime.seconds(), 42); + assert_eq!(clocktime.mseconds(), 42_123); + assert_eq!(clocktime.useconds(), 42_123_456); + assert_eq!(clocktime.nseconds(), 42_123_456_789); // None let clocktime_ron = "None"; - let clocktime: ClockTime = ron::de::from_str(clocktime_ron).unwrap(); - assert_eq!(clocktime.nseconds(), None); + let clocktime: Option = ron::de::from_str(clocktime_ron).unwrap(); + assert!(clocktime.is_none()); let clocktime_json = "null"; - let clocktime: ClockTime = serde_json::from_str(clocktime_json).unwrap(); - assert_eq!(clocktime.nseconds(), None); + let clocktime: Option = serde_json::from_str(clocktime_json).unwrap(); + assert!(clocktime.is_none()); + assert!(clocktime.is_none()); } #[test] fn test_serde_roundtrip() { crate::init().unwrap(); - // Some + // Direct let clocktime = ClockTime::from_nseconds(42_123_456_789); let clocktime_ser = ron::ser::to_string(&clocktime).unwrap(); let clocktime: ClockTime = ron::de::from_str(clocktime_ser.as_str()).unwrap(); - assert_eq!(clocktime.seconds(), Some(42)); - assert_eq!(clocktime.mseconds(), Some(42_123)); - assert_eq!(clocktime.useconds(), Some(42_123_456)); - assert_eq!(clocktime.nseconds(), Some(42_123_456_789)); + assert_eq!(clocktime.seconds(), 42); + assert_eq!(clocktime.mseconds(), 42_123); + assert_eq!(clocktime.useconds(), 42_123_456); + assert_eq!(clocktime.nseconds(), 42_123_456_789); + + // Some + let clocktime = Some(ClockTime::from_nseconds(42_123_456_789)); + let clocktime_ser = ron::ser::to_string(&clocktime).unwrap(); + let clocktime: Option = ron::de::from_str(clocktime_ser.as_str()).unwrap(); + let clocktime = clocktime.unwrap(); + assert_eq!(clocktime.seconds(), 42); + assert_eq!(clocktime.mseconds(), 42_123); + assert_eq!(clocktime.useconds(), 42_123_456); + assert_eq!(clocktime.nseconds(), 42_123_456_789); // None - let clocktime = ClockTime(None); + let clocktime = ClockTime::NONE; let clocktime_ser = ron::ser::to_string(&clocktime).unwrap(); - let clocktime: ClockTime = ron::de::from_str(clocktime_ser.as_str()).unwrap(); - assert_eq!(clocktime.nseconds(), None); + let clocktime: Option = ron::de::from_str(clocktime_ser.as_str()).unwrap(); + assert!(clocktime.is_none()); } } diff --git a/gstreamer/src/element.rs b/gstreamer/src/element.rs index d2e21c47e..b9eb4f52c 100644 --- a/gstreamer/src/element.rs +++ b/gstreamer/src/element.rs @@ -226,11 +226,11 @@ pub trait ElementExtManual: 'static { ) -> Option; #[doc(alias = "gst_element_query_duration")] - fn query_duration(&self) -> Option; + fn query_duration(&self) -> Option; fn query_duration_generic(&self, format: Format) -> Option; #[doc(alias = "gst_element_query_position")] - fn query_position(&self) -> Option; + fn query_position(&self) -> Option; fn query_position_generic(&self, format: Format) -> Option; #[doc(alias = "gst_element_seek")] @@ -265,9 +265,10 @@ pub trait ElementExtManual: 'static { T: Send + 'static; #[doc(alias = "get_current_running_time")] - fn current_running_time(&self) -> crate::ClockTime; + fn current_running_time(&self) -> Option; + #[doc(alias = "get_current_clock_time")] - fn current_clock_time(&self) -> crate::ClockTime; + fn current_clock_time(&self) -> Option; #[cfg(not(feature = "v1_20"))] #[cfg_attr(feature = "dox", doc(cfg(not(feature = "v1_20"))))] @@ -286,11 +287,11 @@ impl> ElementExtManual for O { } fn current_state(&self) -> State { - self.state(ClockTime::zero()).1 + self.state(Some(ClockTime::ZERO)).1 } fn pending_state(&self) -> State { - self.state(ClockTime::zero()).2 + self.state(Some(ClockTime::ZERO)).2 } fn query(&self, query: &mut QueryRef) -> bool { @@ -575,7 +576,7 @@ impl> ElementExtManual for O { let ret = from_glib(ffi::gst_element_query_convert( self.as_ref().to_glib_none().0, src_val.format().into_glib(), - src_val.to_raw_value(), + src_val.into_raw_value(), U::default_format().into_glib(), dest_val.as_mut_ptr(), )); @@ -613,16 +614,16 @@ impl> ElementExtManual for O { } } - fn query_duration(&self) -> Option { + fn query_duration(&self) -> Option { unsafe { let mut duration = mem::MaybeUninit::uninit(); let ret = from_glib(ffi::gst_element_query_duration( self.as_ref().to_glib_none().0, - T::default_format().into_glib(), + T::FormattedValueType::default_format().into_glib(), duration.as_mut_ptr(), )); if ret { - Some(T::from_raw(T::default_format(), duration.assume_init())) + try_from_glib(duration.assume_init()).ok() } else { None } @@ -645,16 +646,16 @@ impl> ElementExtManual for O { } } - fn query_position(&self) -> Option { + fn query_position(&self) -> Option { unsafe { let mut cur = mem::MaybeUninit::uninit(); let ret = from_glib(ffi::gst_element_query_position( self.as_ref().to_glib_none().0, - T::default_format().into_glib(), + T::FormattedValueType::default_format().into_glib(), cur.as_mut_ptr(), )); if ret { - Some(T::from_raw(T::default_format(), cur.assume_init())) + try_from_glib(cur.assume_init()).ok() } else { None } @@ -779,18 +780,18 @@ impl> ElementExtManual for O { Box::pin(async move { receiver.await.expect("sender dropped") }) } - fn current_running_time(&self) -> crate::ClockTime { + fn current_running_time(&self) -> Option { let base_time = self.base_time(); let clock_time = self.current_clock_time(); - clock_time - base_time + clock_time.zip(base_time).map(|(ct, bt)| ct - bt) } - fn current_clock_time(&self) -> crate::ClockTime { + fn current_clock_time(&self) -> Option { if let Some(clock) = self.clock() { clock.time() } else { - crate::CLOCK_TIME_NONE + crate::ClockTime::NONE } } diff --git a/gstreamer/src/event.rs b/gstreamer/src/event.rs index cc6300ed7..90fb920b8 100644 --- a/gstreamer/src/event.rs +++ b/gstreamer/src/event.rs @@ -447,12 +447,12 @@ impl<'a> Caps<'a> { declare_concrete_event!(Segment); impl<'a> Segment<'a> { #[allow(clippy::new_ret_no_self)] - pub fn new(segment: &crate::FormattedSegment) -> Event { + pub fn new(segment: &crate::FormattedSegment) -> Event { skip_assert_initialized!(); Self::builder(segment).build() } - pub fn builder( + pub fn builder( segment: &crate::FormattedSegment, ) -> SegmentBuilder { assert_initialized_main_thread!(); @@ -776,7 +776,7 @@ impl<'a> Gap<'a> { GapBuilder::new(timestamp, duration) } - pub fn get(&self) -> (crate::ClockTime, crate::ClockTime) { + pub fn get(&self) -> (Option, Option) { unsafe { let mut timestamp = mem::MaybeUninit::uninit(); let mut duration = mem::MaybeUninit::uninit(); @@ -818,7 +818,7 @@ impl<'a> Qos<'a> { QosBuilder::new(type_, proportion, diff, timestamp) } - pub fn get(&self) -> (crate::QOSType, f64, i64, crate::ClockTime) { + pub fn get(&self) -> (crate::QOSType, f64, i64, Option) { unsafe { let mut type_ = mem::MaybeUninit::uninit(); let mut proportion = mem::MaybeUninit::uninit(); @@ -919,7 +919,7 @@ impl<'a> Seek<'a> { #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_16")))] #[doc(alias = "get_trickmode_interval")] #[doc(alias = "gst_event_parse_seek_trickmode_interval")] - pub fn trickmode_interval(&self) -> crate::ClockTime { + pub fn trickmode_interval(&self) -> Option { unsafe { let mut trickmode_interval = mem::MaybeUninit::uninit(); @@ -962,7 +962,7 @@ impl<'a> Latency<'a> { #[doc(alias = "get_latency")] #[doc(alias = "gst_event_parse_latency")] - pub fn latency(&self) -> crate::ClockTime { + pub fn latency(&self) -> Option { unsafe { let mut latency = mem::MaybeUninit::uninit(); diff --git a/gstreamer/src/format.rs b/gstreamer/src/format.rs index 5e6b1d10b..96521a692 100644 --- a/gstreamer/src/format.rs +++ b/gstreamer/src/format.rs @@ -2,45 +2,65 @@ use crate::ClockTime; use crate::Format; +use glib::translate::{FromGlib, GlibNoneError, IntoGlib, OptionIntoGlib, TryFromGlib}; use muldiv::MulDiv; +use std::borrow::Borrow; use std::convert::TryFrom; +use std::fmt; use std::ops; use thiserror::Error; -use std::cmp; - #[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)] #[cfg_attr(feature = "ser_de", derive(serde::Serialize, serde::Deserialize))] pub enum GenericFormattedValue { Undefined(Undefined), - Default(Default), - Bytes(Bytes), - Time(ClockTime), - Buffers(Buffers), - Percent(Percent), + Default(Option), + Bytes(Option), + Time(Option), + Buffers(Option), + Percent(Option), Other(Format, i64), } #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Debug, Default)] pub struct Undefined(pub i64); -#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug, Default)] -pub struct Default(pub Option); -impl_common_ops_for_opt_int!(Default); +#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Debug, Default)] +pub struct Default(pub u64); -#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug, Default)] -pub struct Bytes(pub Option); -impl_common_ops_for_opt_int!(Bytes); +#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Debug, Default)] +pub struct Bytes(pub u64); pub type Time = ClockTime; -#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug, Default)] -pub struct Buffers(pub Option); -impl_common_ops_for_opt_int!(Buffers); +#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Debug, Default)] +pub struct Buffers(pub u64); +impl Buffers { + pub const OFFSET_NONE: u64 = ffi::GST_BUFFER_OFFSET_NONE; +} -#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug, Default)] -pub struct Percent(pub Option); -impl_common_ops_for_opt_int!(Percent); +#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Debug, Default)] +pub struct Percent(pub u32); +impl Percent { + pub const MAX: u32 = ffi::GST_FORMAT_PERCENT_MAX as u32; + pub const SCALE: u32 = ffi::GST_FORMAT_PERCENT_SCALE as u32; +} + +impl fmt::Display for GenericFormattedValue { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use crate::utils::Displayable; + + match self { + Self::Undefined(val) => val.fmt(f), + Self::Default(val) => val.display().fmt(f), + Self::Bytes(val) => val.display().fmt(f), + Self::Time(val) => val.display().fmt(f), + Self::Buffers(val) => val.display().fmt(f), + Self::Percent(val) => val.display().fmt(f), + Self::Other(format, val) => write!(f, "{} ({:?})", val, format), + } + } +} #[derive(Clone, Copy, Debug, PartialEq, Eq, Error)] #[error("invalid generic value format")] @@ -53,11 +73,32 @@ pub trait FormattedValue: Copy + Clone + Sized + Into + ' fn format(&self) -> Format; unsafe fn from_raw(format: Format, value: i64) -> Self; - unsafe fn to_raw_value(&self) -> i64; + unsafe fn into_raw_value(self) -> i64; +} + +// rustdoc-stripper-ignore-next +/// A trait implemented on the intrinsic type of a `FormattedValue`. +/// +/// # Examples +/// +/// - `GenericFormattedValue` is the intrinsic type for `GenericFormattedValue`. +/// - `Undefined` is the intrinsic type for `Undefined`. +/// - `Bytes` is the intrinsic type for `Option`. +pub trait FormattedValueIntrinsic: Copy + Clone + Sized + 'static { + type FormattedValueType: FormattedValue; } pub trait SpecificFormattedValue: FormattedValue + TryFrom {} +// rustdoc-stripper-ignore-next +/// A trait implemented on the intrinsic type of a `SpecificFormattedValue`. +/// +/// # Examples +/// +/// - `Undefined` is the intrinsic type for `Undefined`. +/// - `Bytes` is the intrinsic type for `Option`. +pub trait SpecificFormattedValueIntrinsic: TryFromGlib + FormattedValueIntrinsic {} + impl FormattedValue for GenericFormattedValue { fn default_format() -> Format { Format::Undefined @@ -71,7 +112,7 @@ impl FormattedValue for GenericFormattedValue { GenericFormattedValue::new(format, value) } - unsafe fn to_raw_value(&self) -> i64 { + unsafe fn into_raw_value(self) -> i64 { self.value() } } @@ -81,27 +122,11 @@ impl GenericFormattedValue { skip_assert_initialized!(); match format { Format::Undefined => Self::Undefined(Undefined(value)), - Format::Default => Self::Default(if value == -1 { - Default(None) - } else { - Default(Some(value as u64)) - }), - Format::Bytes => Self::Bytes(if value == -1 { - Bytes(None) - } else { - Bytes(Some(value as u64)) - }), - Format::Time => Self::Time(if value == -1 { - ClockTime::none() - } else { - ClockTime::from_nseconds(value as u64) - }), - Format::Buffers => Self::Buffers(if value == -1 { - Buffers(None) - } else { - Buffers(Some(value as u64)) - }), - Format::Percent => Self::Percent(unsafe { Percent::from_raw(format, value) }), + Format::Default => Self::Default(unsafe { FromGlib::from_glib(value as u64) }), + Format::Bytes => Self::Bytes(unsafe { FromGlib::from_glib(value as u64) }), + Format::Time => Self::Time(unsafe { FromGlib::from_glib(value as u64) }), + Format::Buffers => Self::Buffers(unsafe { FromGlib::from_glib(value as u64) }), + Format::Percent => Self::Percent(unsafe { FormattedValue::from_raw(format, value) }), Format::__Unknown(_) => Self::Other(format, value), } } @@ -121,153 +146,87 @@ impl GenericFormattedValue { #[doc(alias = "get_value")] pub fn value(&self) -> i64 { - match *self { - Self::Undefined(v) => v.0, - Self::Default(v) => v.map(|v| v as i64).unwrap_or(-1), - Self::Bytes(v) => v.map(|v| v as i64).unwrap_or(-1), - Self::Time(v) => v.map(|v| v as i64).unwrap_or(-1), - Self::Buffers(v) => v.map(|v| v as i64).unwrap_or(-1), - Self::Percent(v) => v.map(i64::from).unwrap_or(-1), - Self::Other(_, v) => v, + unsafe { + match *self { + Self::Undefined(v) => v.0, + Self::Default(v) => v.into_raw_value(), + Self::Bytes(v) => v.into_raw_value(), + Self::Time(v) => v.into_raw_value(), + Self::Buffers(v) => v.into_raw_value(), + Self::Percent(v) => v.into_raw_value(), + Self::Other(_, v) => v, + } } } } +impl FormattedValueIntrinsic for GenericFormattedValue { + type FormattedValueType = GenericFormattedValue; +} + macro_rules! impl_op_same( - ($name:ident, $op:ident, $op_name:ident, $op_assign:ident, $op_assign_name:ident, $e:expr) => { - impl ops::$op<$name> for $name { + ($name:ident, $op:ident, $op_name:ident, $op_assign:ident, $op_assign_name:ident) => { + impl> ops::$op for $name { + type Output = Self; + + fn $op_name(self, rhs: RHS) -> Self::Output { + Self(self.0.$op_name(rhs.borrow().0)) + } + } + + impl> ops::$op for &$name { type Output = $name; - fn $op_name(self, other: $name) -> Self::Output { - match (self.0, other.0) { - (Some(a), Some(b)) => $name($e(a, b)), - _ => $name(None), - } + fn $op_name(self, rhs: RHS) -> Self::Output { + (*self).$op_name(rhs) } } - impl<'a> ops::$op<&'a $name> for $name { - type Output = $name; - - fn $op_name(self, other: &'a $name) -> Self::Output { - self.$op_name(*other) - } - } - - impl<'a> ops::$op<$name> for &'a $name { - type Output = $name; - - fn $op_name(self, other: $name) -> Self::Output { - (*self).$op_name(other) - } - } - - impl<'a, 'b> ops::$op<&'a $name> for &'b $name { - type Output = $name; - - fn $op_name(self, other: &'a $name) -> Self::Output { - (*self).$op_name(*other) - } - } - - impl ops::$op_assign<$name> for $name { - fn $op_assign_name(&mut self, other: $name) { - match (self.0, other.0) { - (Some(a), Some(b)) => self.0 = $e(a, b), - _ => self.0 = None, - } - } - } - - impl<'a> ops::$op_assign<&'a $name> for $name { - fn $op_assign_name(&mut self, other: &'a $name) { - self.$op_assign_name(*other) + impl> ops::$op_assign for $name { + fn $op_assign_name(&mut self, rhs: RHS) { + self.0.$op_assign_name(rhs.borrow().0) } } }; ); macro_rules! impl_op_u64( - ($name:ident, $op:ident, $op_name:ident, $op_assign:ident, $op_assign_name:ident, $e:expr) => { + ($name:ident, $op:ident, $op_name:ident, $op_assign:ident, $op_assign_name:ident) => { impl ops::$op for $name { type Output = $name; - fn $op_name(self, other: u64) -> Self::Output { - match self.0 { - Some(a) => $name($e(a, other)), - _ => $name(None), - } + fn $op_name(self, rhs: u64) -> Self::Output { + $name(self.0.$op_name(rhs)) } } - impl<'a> ops::$op<&'a u64> for $name { + impl ops::$op for &$name { type Output = $name; - fn $op_name(self, other: &'a u64) -> Self::Output { - self.$op_name(*other) - } - } - - impl<'a> ops::$op for &'a $name { - type Output = $name; - - fn $op_name(self, other: u64) -> Self::Output { - (*self).$op_name(other) - } - } - - impl<'a, 'b> ops::$op<&'a u64> for &'b $name { - type Output = $name; - - fn $op_name(self, other: &'a u64) -> Self::Output { - self.$op_name(*other) + fn $op_name(self, rhs: u64) -> Self::Output { + (*self).$op_name(rhs) } } impl ops::$op<$name> for u64 { type Output = $name; - fn $op_name(self, other: $name) -> $name { - other.$op_name(self) + fn $op_name(self, rhs: $name) -> $name { + $name(self.$op_name(rhs.0)) } } - impl<'a> ops::$op<&'a $name> for u64 { + impl ops::$op<&$name> for u64 { type Output = $name; - fn $op_name(self, other: &'a $name) -> $name { - (*other).$op_name(self) - } - } - - impl<'a> ops::$op<$name> for &'a u64 { - type Output = $name; - - fn $op_name(self, other: $name) -> $name { - other.$op_name(*self) - } - } - - impl<'a, 'b> ops::$op<&'a $name> for &'b u64 { - type Output = $name; - - fn $op_name(self, other: &'a $name) -> $name { - (*other).$op_name(*self) + fn $op_name(self, rhs: &$name) -> $name { + self.$op_name(*rhs) } } impl ops::$op_assign for $name { - fn $op_assign_name(&mut self, other: u64) { - match self.0 { - Some(a) => self.0 = $e(a, other), - _ => self.0 = None, - } - } - } - - impl<'a> ops::$op_assign<&'a u64> for $name { - fn $op_assign_name(&mut self, other: &'a u64) { - self.$op_assign_name(*other) + fn $op_assign_name(&mut self, rhs: u64) { + self.0.$op_assign_name(rhs) } } }; @@ -275,7 +234,7 @@ macro_rules! impl_op_u64( macro_rules! impl_format_value_traits( ($name:ident, $format:ident, $format_value:ident) => { - impl FormattedValue for $name { + impl FormattedValue for Option<$name> { fn default_format() -> Format { Format::$format } @@ -284,31 +243,38 @@ macro_rules! impl_format_value_traits( Format::$format } - unsafe fn from_raw(format: Format, value: i64) -> Self { + unsafe fn from_raw(format: Format, value: i64) -> Option<$name> { debug_assert_eq!(format, Format::$format); - if value == -1 { - $name(None) - } else { - $name(Some(value as u64)) - } + FromGlib::from_glib(value as u64) } - unsafe fn to_raw_value(&self) -> i64 { - self.0.map(|v| v as i64).unwrap_or(-1) + unsafe fn into_raw_value(self) -> i64 { + IntoGlib::into_glib(self) as i64 + } + } + + impl From> for GenericFormattedValue { + fn from(v: Option<$name>) -> Self { + skip_assert_initialized!(); + Self::$format_value(v) } } impl From<$name> for GenericFormattedValue { fn from(v: $name) -> Self { - skip_assert_initialized!(); - GenericFormattedValue::$format_value(v) + skip_assert_initialized!(); + Self::$format_value(Some(v)) } } - impl TryFrom for $name { + impl FormattedValueIntrinsic for $name { + type FormattedValueType = Option<$name>; + } + + impl TryFrom for Option<$name> { type Error = TryFromGenericFormattedValueError; - fn try_from(v: GenericFormattedValue) -> Result<$name, Self::Error> { + fn try_from(v: GenericFormattedValue) -> Result, Self::Error> { skip_assert_initialized!(); if let GenericFormattedValue::$format_value(v) = v { Ok(v) @@ -318,208 +284,127 @@ macro_rules! impl_format_value_traits( } } - impl SpecificFormattedValue for $name { } + impl TryFrom for $name { + type Error = GlibNoneError; - impl From for $name { - fn from(v: u64) -> Self { + fn try_from(v: u64) -> Result<$name, GlibNoneError> { skip_assert_initialized!(); - $name(Some(v)) + unsafe { Self::try_from_glib(v) } } } - impl From> for $name { - fn from(v: Option) -> Self { + impl TryFromGlib for $name { + type Error = GlibNoneError; + #[inline] + unsafe fn try_from_glib(val: i64) -> Result { skip_assert_initialized!(); - $name(v) + <$name as TryFromGlib>::try_from_glib(val as u64) } } - impl From<$name> for Option { - fn from(v: $name) -> Self { - skip_assert_initialized!(); - v.0 - } - } + impl SpecificFormattedValue for Option<$name> {} + impl SpecificFormattedValueIntrinsic for $name {} impl ops::Deref for $name { - type Target = Option; + type Target = u64; - fn deref(&self) -> &Option { + fn deref(&self) -> &u64 { &self.0 } } impl ops::DerefMut for $name { - fn deref_mut(&mut self) -> &mut Option { + fn deref_mut(&mut self) -> &mut u64 { &mut self.0 } } - impl AsRef> for $name { - fn as_ref(&self) -> &Option { + impl AsRef for $name { + fn as_ref(&self) -> &u64 { &self.0 } } - impl AsMut> for $name { - fn as_mut(&mut self) -> &mut Option { + impl AsMut for $name { + fn as_mut(&mut self) -> &mut u64 { &mut self.0 } } - impl_op_same!($name, Add, add, AddAssign, add_assign, |a: u64, b: u64| a.checked_add(b)); - impl_op_same!($name, Sub, sub, SubAssign, sub_assign, |a: u64, b: u64| a.checked_sub(b)); - impl_op_same!($name, Mul, mul, MulAssign, mul_assign, |a: u64, b: u64| a.checked_mul(b)); - impl_op_same!($name, Div, div, DivAssign, div_assign, |a: u64, b: u64| a.checked_div(b)); - impl_op_same!($name, Rem, rem, RemAssign, rem_assign, |a: u64, b: u64| a.checked_rem(b)); + impl_op_same!($name, Add, add, AddAssign, add_assign); + impl_op_same!($name, Sub, sub, SubAssign, sub_assign); + impl_op_same!($name, Mul, mul, MulAssign, mul_assign); + impl_op_same!($name, Div, div, DivAssign, div_assign); + impl_op_same!($name, Rem, rem, RemAssign, rem_assign); - impl_op_u64!($name, Mul, mul, MulAssign, mul_assign, |a: u64, b: u64| a.checked_mul(b)); - impl_op_u64!($name, Div, div, DivAssign, div_assign, |a: u64, b: u64| a.checked_div(b)); - impl_op_u64!($name, Rem, rem, RemAssign, rem_assign, |a: u64, b: u64| a.checked_rem(b)); + impl_op_u64!($name, Mul, mul, MulAssign, mul_assign); + impl_op_u64!($name, Div, div, DivAssign, div_assign); + impl_op_u64!($name, Rem, rem, RemAssign, rem_assign); - impl MulDiv<$name> for $name { + impl> MulDiv for $name { type Output = $name; - fn mul_div_floor(self, num: $name, denom: $name) -> Option { - match (self.0, num.0, denom.0) { - (Some(s), Some(n), Some(d)) => s.mul_div_floor(n, d).map(|v| $name(Some(v))), - _ => Some($name(None)), - } + fn mul_div_floor(self, num: ND, denom: ND) -> Option { + self.0 + .mul_div_floor(*num.borrow(), *denom.borrow()) + .map($name) } - fn mul_div_round(self, num: $name, denom: $name) -> Option { - match (self.0, num.0, denom.0) { - (Some(s), Some(n), Some(d)) => s.mul_div_round(n, d).map(|v| $name(Some(v))), - _ => Some($name(None)), - } + fn mul_div_round(self, num: ND, denom: ND) -> Option { + self.0 + .mul_div_round(*num.borrow(), *denom.borrow()) + .map($name) } - fn mul_div_ceil(self, num: $name, denom: $name) -> Option { - match (self.0, num.0, denom.0) { - (Some(s), Some(n), Some(d)) => s.mul_div_ceil(n, d).map(|v| $name(Some(v))), - _ => Some($name(None)), - } - } - } - - impl<'a> MulDiv<&'a $name> for $name { - type Output = $name; - - fn mul_div_floor(self, num: &$name, denom: &$name) -> Option { - self.mul_div_floor(*num, *denom) - } - - fn mul_div_round(self, num: &$name, denom: &$name) -> Option { - self.mul_div_round(*num, *denom) - } - - fn mul_div_ceil(self, num: &$name, denom: &$name) -> Option { - self.mul_div_ceil(*num, *denom) - } - } - - impl<'a> MulDiv<$name> for &'a $name { - type Output = $name; - - fn mul_div_floor(self, num: $name, denom: $name) -> Option { - (*self).mul_div_floor(num, denom) - } - - fn mul_div_round(self, num: $name, denom: $name) -> Option { - (*self).mul_div_round(num, denom) - } - - fn mul_div_ceil(self, num: $name, denom: $name) -> Option { - (*self).mul_div_ceil(num, denom) - } - } - - impl<'a, 'b> MulDiv<&'b $name> for &'a $name { - type Output = $name; - - fn mul_div_floor(self, num: &$name, denom: &$name) -> Option { - (*self).mul_div_floor(*num, *denom) - } - - fn mul_div_round(self, num: &$name, denom: &$name) -> Option { - (*self).mul_div_round(*num, *denom) - } - - fn mul_div_ceil(self, num: &$name, denom: &$name) -> Option { - (*self).mul_div_ceil(*num, *denom) - } - } - - impl<'a> MulDiv for $name { - type Output = $name; - - fn mul_div_floor(self, num: u64, denom: u64) -> Option { - self.mul_div_floor($name(Some(num)), $name(Some(denom))) - } - - fn mul_div_round(self, num: u64, denom: u64) -> Option { - self.mul_div_round($name(Some(num)), $name(Some(denom))) - } - - fn mul_div_ceil(self, num: u64, denom: u64) -> Option { - self.mul_div_ceil($name(Some(num)), $name(Some(denom))) - } - } - - impl<'a> MulDiv<&'a u64> for $name { - type Output = $name; - - fn mul_div_floor(self, num: &u64, denom: &u64) -> Option { - self.mul_div_floor(*num, *denom) - } - - fn mul_div_round(self, num: &u64, denom: &u64) -> Option { - self.mul_div_round(*num, *denom) - } - - fn mul_div_ceil(self, num: &u64, denom: &u64) -> Option { - self.mul_div_ceil(*num, *denom) - } - } - - impl<'a> MulDiv for &'a $name { - type Output = $name; - - fn mul_div_floor(self, num: u64, denom: u64) -> Option { - (*self).mul_div_floor(num, denom) - } - - fn mul_div_round(self, num: u64, denom: u64) -> Option { - (*self).mul_div_round(num, denom) - } - - fn mul_div_ceil(self, num: u64, denom: u64) -> Option { - (*self).mul_div_ceil(num, denom) - } - } - - impl<'a, 'b> MulDiv<&'a u64> for &'b $name { - type Output = $name; - - fn mul_div_floor(self, num: &u64, denom: &u64) -> Option { - (*self).mul_div_floor(*num, *denom) - } - - fn mul_div_round(self, num: &u64, denom: &u64) -> Option { - (*self).mul_div_round(*num, *denom) - } - - fn mul_div_ceil(self, num: &u64, denom: &u64) -> Option { - (*self).mul_div_ceil(*num, *denom) + fn mul_div_ceil(self, num: ND, denom: ND) -> Option { + self.0 + .mul_div_ceil(*num.borrow(), *denom.borrow()) + .map($name) } } }; ); +macro_rules! option_glib_newtype_display { + ($name:ident, $unit:expr) => { + impl crate::utils::Displayable for Option<$name> { + type DisplayImpl = String; + + fn display(self) -> String { + if let Some(val) = self { + val.display() + } else { + format!("undef. {}", $unit) + } + } + } + + impl crate::utils::Displayable for $name { + type DisplayImpl = String; + + fn display(self) -> String { + format!("{} {}", self.0, $unit) + } + } + }; +} + +impl_common_ops_for_newtype_u64!(Default); impl_format_value_traits!(Default, Default, Default); +option_glib_newtype_from_to!(Default, u64::MAX); +option_glib_newtype_display!(Default, "(Default)"); + +impl_common_ops_for_newtype_u64!(Bytes); impl_format_value_traits!(Bytes, Bytes, Bytes); +option_glib_newtype_from_to!(Bytes, u64::MAX); +option_glib_newtype_display!(Bytes, "bytes"); + impl_format_value_traits!(ClockTime, Time, Time); + +impl_common_ops_for_newtype_u64!(Buffers); impl_format_value_traits!(Buffers, Buffers, Buffers); +option_glib_newtype_from_to!(Buffers, Buffers::OFFSET_NONE); +option_glib_newtype_display!(Buffers, "buffers"); impl FormattedValue for Undefined { fn default_format() -> Format { @@ -535,7 +420,7 @@ impl FormattedValue for Undefined { Undefined(value) } - unsafe fn to_raw_value(&self) -> i64 { + unsafe fn into_raw_value(self) -> i64 { self.0 } } @@ -560,8 +445,23 @@ impl TryFrom for Undefined { } } +impl FormattedValueIntrinsic for Undefined { + type FormattedValueType = Undefined; +} + impl SpecificFormattedValue for Undefined {} +impl SpecificFormattedValueIntrinsic for Undefined {} + +impl TryFromGlib for Undefined { + type Error = std::convert::Infallible; + #[inline] + unsafe fn try_from_glib(v: i64) -> Result { + skip_assert_initialized!(); + Ok(Undefined(v)) + } +} + impl From for Undefined { fn from(v: i64) -> Self { skip_assert_initialized!(); @@ -569,13 +469,6 @@ impl From for Undefined { } } -impl From for i64 { - fn from(u: Undefined) -> Self { - skip_assert_initialized!(); - u.0 - } -} - impl ops::Deref for Undefined { type Target = i64; @@ -602,7 +495,24 @@ impl AsMut for Undefined { } } -impl FormattedValue for Percent { +impl fmt::Display for Undefined { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{} (Undefined)", self.0) + } +} + +impl crate::utils::Displayable for Undefined { + type DisplayImpl = Undefined; + + fn display(self) -> Undefined { + self + } +} + +impl_common_ops_for_newtype_u64!(Percent); +option_glib_newtype_display!(Percent, "%"); + +impl FormattedValue for Option { fn default_format() -> Format { Format::Percent } @@ -613,29 +523,47 @@ impl FormattedValue for Percent { unsafe fn from_raw(format: Format, value: i64) -> Self { debug_assert_eq!(format, Format::Percent); - if value < 0 || value > ffi::GST_FORMAT_PERCENT_MAX { - Percent(None) - } else { - Percent(Some(value as u32)) - } + Percent::try_from_glib(value as i64).ok() } - unsafe fn to_raw_value(&self) -> i64 { - self.0.map(|v| v as i64).unwrap_or(-1) + unsafe fn into_raw_value(self) -> i64 { + self.map_or(-1, |v| v.0 as i64) + } +} + +impl From> for GenericFormattedValue { + fn from(v: Option) -> Self { + skip_assert_initialized!(); + GenericFormattedValue::Percent(v) } } impl From for GenericFormattedValue { fn from(v: Percent) -> Self { skip_assert_initialized!(); - GenericFormattedValue::Percent(v) + GenericFormattedValue::Percent(Some(v)) } } -impl TryFrom for Percent { +impl TryFromGlib for Percent { + type Error = GlibNoneError; + #[inline] + unsafe fn try_from_glib(value: i64) -> Result { + skip_assert_initialized!(); + if value < 0 || value > ffi::GST_FORMAT_PERCENT_MAX { + Err(GlibNoneError) + } else { + Ok(Percent(value as u32)) + } + } +} + +impl TryFrom for Option { type Error = TryFromGenericFormattedValueError; - fn try_from(v: GenericFormattedValue) -> Result { + fn try_from( + v: GenericFormattedValue, + ) -> Result, TryFromGenericFormattedValueError> { skip_assert_initialized!(); if let GenericFormattedValue::Percent(v) = v { Ok(v) @@ -645,30 +573,36 @@ impl TryFrom for Percent { } } -impl SpecificFormattedValue for Percent {} +impl FormattedValueIntrinsic for Percent { + type FormattedValueType = Option; +} + +impl SpecificFormattedValue for Option {} + +impl SpecificFormattedValueIntrinsic for Percent {} impl ops::Deref for Percent { - type Target = Option; + type Target = u32; - fn deref(&self) -> &Option { + fn deref(&self) -> &u32 { &self.0 } } impl ops::DerefMut for Percent { - fn deref_mut(&mut self) -> &mut Option { + fn deref_mut(&mut self) -> &mut u32 { &mut self.0 } } -impl AsRef> for Percent { - fn as_ref(&self) -> &Option { +impl AsRef for Percent { + fn as_ref(&self) -> &u32 { &self.0 } } -impl AsMut> for Percent { - fn as_mut(&mut self) -> &mut Option { +impl AsMut for Percent { + fn as_mut(&mut self) -> &mut u32 { &mut self.0 } } @@ -685,9 +619,9 @@ impl TryFrom for Percent { if v < 0.0 || v > 1.0 { Err(TryPercentFromFloatError(())) } else { - Ok(Percent(Some( - (v * ffi::GST_FORMAT_PERCENT_SCALE as f64).round() as u32, - ))) + Ok(Percent( + (v * ffi::GST_FORMAT_PERCENT_SCALE as f64).round() as u32 + )) } } } @@ -700,28 +634,9 @@ impl TryFrom for Percent { if v < 0.0 || v > 1.0 { Err(TryPercentFromFloatError(())) } else { - Ok(Percent(Some( - (v * ffi::GST_FORMAT_PERCENT_SCALE as f32).round() as u32, - ))) + Ok(Percent( + (v * ffi::GST_FORMAT_PERCENT_SCALE as f32).round() as u32 + )) } } } - -#[cfg(test)] -mod tests { - #[test] - fn test_clock_time() { - crate::init().unwrap(); - - let t1 = crate::SECOND; - let t2 = 2 * t1; - let t3 = &t1 * 2; - let mut t4 = t2 + t3; - t4 += &t1; - - assert_eq!(t4.nanoseconds(), Some(5_000_000_000)); - - let t5 = t4 - 6 * crate::SECOND; - assert!(t5.is_none()); - } -} diff --git a/gstreamer/src/format_serde.rs b/gstreamer/src/format_serde.rs index 80fe5e04a..8c34f327b 100644 --- a/gstreamer/src/format_serde.rs +++ b/gstreamer/src/format_serde.rs @@ -19,7 +19,7 @@ macro_rules! impl_ser_de( impl<'de> Deserialize<'de> for $t { fn deserialize>(deserializer: D) -> Result { skip_assert_initialized!(); - Option::::deserialize(deserializer).map($t) + u64::deserialize(deserializer).map($t) } } } @@ -51,7 +51,7 @@ impl Serialize for Percent { impl<'de> Deserialize<'de> for Percent { fn deserialize>(deserializer: D) -> Result { skip_assert_initialized!(); - Option::::deserialize(deserializer).map(Percent) + u32::deserialize(deserializer).map(Percent) } } @@ -69,43 +69,43 @@ mod tests { let pretty_config = ron::ser::PrettyConfig::new().with_new_line("".to_string()); - let value = GenericFormattedValue::Undefined(Undefined::from(42)); + let value = GenericFormattedValue::from(Undefined(42)); let res = ron::ser::to_string_pretty(&value, pretty_config.clone()); assert_eq!(Ok("Undefined(42)".to_owned()), res); let res = serde_json::to_string(&value).unwrap(); assert_eq!("{\"Undefined\":42}".to_owned(), res); - let value = GenericFormattedValue::Default(Default::from(42)); + let value = GenericFormattedValue::from(Default(42)); 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(); assert_eq!("{\"Default\":42}".to_owned(), res); - let value = GenericFormattedValue::Default(Default::from(None)); + let value = GenericFormattedValue::from(Option::::None); let res = ron::ser::to_string_pretty(&value, pretty_config.clone()); assert_eq!(Ok("Default(None)".to_owned()), res); let res = serde_json::to_string(&value).unwrap(); assert_eq!("{\"Default\":null}".to_owned(), res); - let value = GenericFormattedValue::Bytes(Bytes::from(42)); + let value = GenericFormattedValue::from(Bytes(42)); 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(); assert_eq!("{\"Bytes\":42}".to_owned(), res); - let value = GenericFormattedValue::Time(ClockTime::from_nseconds(42_123_456_789)); + let value = GenericFormattedValue::from(ClockTime::from_nseconds(42_123_456_789)); let res = ron::ser::to_string_pretty(&value, pretty_config.clone()); assert_eq!(Ok("Time(Some(42123456789))".to_owned()), res); let res = serde_json::to_string(&value).unwrap(); assert_eq!("{\"Time\":42123456789}".to_owned(), res); - let value = GenericFormattedValue::Buffers(Buffers::from(42)); + let value = GenericFormattedValue::from(Buffers(42)); 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::Percent(Percent::try_from(0.42).unwrap()); + let value = GenericFormattedValue::from(Percent::try_from(0.42).unwrap()); 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(); @@ -130,11 +130,11 @@ mod tests { let value_ron = "Default(Some(42))"; let value_de: GenericFormattedValue = ron::de::from_str(value_ron).unwrap(); - assert_eq!(value_de, GenericFormattedValue::Default(Default::from(42))); + assert_eq!(value_de, GenericFormattedValue::from(Default(42))); let value_json = "{\"Default\":42}"; let value_de: GenericFormattedValue = serde_json::from_str(value_json).unwrap(); - assert_eq!(value_de, GenericFormattedValue::Default(Default::from(42))); + assert_eq!(value_de, GenericFormattedValue::from(Default(42))); let value_ron = "Other(Percent, 42)"; let value_de: GenericFormattedValue = ron::de::from_str(value_ron).unwrap(); @@ -158,13 +158,13 @@ mod tests { ); test_roundrip!(GenericFormattedValue::Undefined(Undefined::from(42))); - test_roundrip!(GenericFormattedValue::Default(Default::from(42))); - test_roundrip!(GenericFormattedValue::Bytes(Bytes(Some(42)))); - test_roundrip!(GenericFormattedValue::Time(ClockTime::from_nseconds( + test_roundrip!(GenericFormattedValue::from(Default(42))); + test_roundrip!(GenericFormattedValue::from(Bytes(42))); + test_roundrip!(GenericFormattedValue::from(ClockTime::from_nseconds( 42_123_456_789 ))); - test_roundrip!(GenericFormattedValue::Buffers(Buffers::from(42))); - test_roundrip!(GenericFormattedValue::Percent( + test_roundrip!(GenericFormattedValue::from(Buffers(42))); + test_roundrip!(GenericFormattedValue::from( Percent::try_from(0.42).unwrap() )); test_roundrip!(GenericFormattedValue::Other(Format::Percent, 42)); diff --git a/gstreamer/src/lib.rs b/gstreamer/src/lib.rs index 1ed0a0008..2999e09d8 100644 --- a/gstreamer/src/lib.rs +++ b/gstreamer/src/lib.rs @@ -202,7 +202,10 @@ mod typefind; pub use crate::typefind::*; pub mod format; -pub use crate::format::{FormattedValue, GenericFormattedValue, SpecificFormattedValue}; +pub use crate::format::{ + FormattedValue, FormattedValueIntrinsic, GenericFormattedValue, SpecificFormattedValue, + SpecificFormattedValueIntrinsic, +}; #[cfg(feature = "ser_de")] mod format_serde; @@ -230,6 +233,8 @@ pub use crate::param_spec::*; pub mod functions; pub use crate::functions::*; +mod utils; + use std::ptr; #[doc(alias = "gst_init_check")] @@ -259,22 +264,6 @@ pub unsafe fn deinit() { ffi::gst_deinit(); } -pub const BUFFER_OFFSET_NONE: u64 = ffi::GST_BUFFER_OFFSET_NONE; -pub const CLOCK_TIME_NONE: ClockTime = ClockTime(None); - -pub const SECOND: ClockTime = ClockTime(Some(1_000_000_000)); -pub const MSECOND: ClockTime = ClockTime(Some(1_000_000)); -pub const USECOND: ClockTime = ClockTime(Some(1_000)); -pub const NSECOND: ClockTime = ClockTime(Some(1)); - -pub const SECOND_VAL: u64 = 1_000_000_000; -pub const MSECOND_VAL: u64 = 1_000_000; -pub const USECOND_VAL: u64 = 1_000; -pub const NSECOND_VAL: u64 = 1; - -pub const FORMAT_PERCENT_MAX: u32 = ffi::GST_FORMAT_PERCENT_MAX as u32; -pub const FORMAT_PERCENT_SCALE: u32 = ffi::GST_FORMAT_PERCENT_SCALE as u32; - pub const PARAM_FLAG_CONTROLLABLE: glib::ParamFlags = glib::ParamFlags::USER_1; pub const PARAM_FLAG_MUTABLE_READY: glib::ParamFlags = glib::ParamFlags::USER_2; pub const PARAM_FLAG_MUTABLE_PAUSED: glib::ParamFlags = glib::ParamFlags::USER_3; @@ -333,10 +322,12 @@ pub mod prelude { pub use muldiv::MulDiv; - pub use crate::format::{FormattedValue, SpecificFormattedValue}; + pub use crate::format::{ + FormattedValue, FormattedValueIntrinsic, SpecificFormattedValue, + SpecificFormattedValueIntrinsic, + }; + pub use crate::utils::Displayable; } -mod utils; - #[macro_use] pub mod subclass; diff --git a/gstreamer/src/message.rs b/gstreamer/src/message.rs index fbf947832..8f62498b7 100644 --- a/gstreamer/src/message.rs +++ b/gstreamer/src/message.rs @@ -956,7 +956,7 @@ impl<'a> AsyncDone<'a> { } #[doc(alias = "get_running_time")] - pub fn running_time(&self) -> crate::ClockTime { + pub fn running_time(&self) -> Option { unsafe { let mut running_time = mem::MaybeUninit::uninit(); @@ -1079,10 +1079,10 @@ impl<'a> Qos<'a> { &self, ) -> ( bool, - crate::ClockTime, - crate::ClockTime, - crate::ClockTime, - crate::ClockTime, + Option, + Option, + Option, + Option, ) { unsafe { let mut live = mem::MaybeUninit::uninit(); @@ -1241,7 +1241,7 @@ impl<'a> ResetTime<'a> { } #[doc(alias = "get_running_time")] - pub fn running_time(&self) -> crate::ClockTime { + pub fn running_time(&self) -> Option { unsafe { let mut running_time = mem::MaybeUninit::uninit(); diff --git a/gstreamer/src/meta.rs b/gstreamer/src/meta.rs index 393c8beec..4d7498753 100644 --- a/gstreamer/src/meta.rs +++ b/gstreamer/src/meta.rs @@ -377,7 +377,7 @@ impl ReferenceTimestampMeta { buffer: &'a mut BufferRef, reference: &Caps, timestamp: ClockTime, - duration: ClockTime, + duration: impl Into>, ) -> MetaRefMut<'a, Self, Standalone> { skip_assert_initialized!(); unsafe { @@ -385,7 +385,7 @@ impl ReferenceTimestampMeta { buffer.as_mut_ptr(), reference.to_glib_none().0, timestamp.into_glib(), - duration.into_glib(), + duration.into().into_glib(), ); Self::from_mut_ptr(buffer, meta) @@ -403,12 +403,12 @@ impl ReferenceTimestampMeta { } #[doc(alias = "get_timestamp")] - pub fn timestamp(&self) -> ClockTime { + pub fn timestamp(&self) -> Option { unsafe { from_glib(self.0.timestamp) } } #[doc(alias = "get_duration")] - pub fn duration(&self) -> ClockTime { + pub fn duration(&self) -> Option { unsafe { from_glib(self.0.duration) } } } @@ -428,10 +428,12 @@ unsafe impl MetaAPI for ReferenceTimestampMeta { #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_14")))] impl fmt::Debug for ReferenceTimestampMeta { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use crate::utils::Displayable; + f.debug_struct("ReferenceTimestampMeta") .field("reference", &self.reference()) - .field("timestamp", &self.timestamp()) - .field("duration", &self.duration()) + .field("timestamp", &self.timestamp().display().to_string()) + .field("duration", &self.duration().display().to_string()) .finish() } } diff --git a/gstreamer/src/pad.rs b/gstreamer/src/pad.rs index 4788bcace..f3284e2de 100644 --- a/gstreamer/src/pad.rs +++ b/gstreamer/src/pad.rs @@ -16,8 +16,8 @@ use crate::PadProbeReturn; use crate::PadProbeType; use crate::Query; use crate::QueryRef; -use crate::SpecificFormattedValue; use crate::StaticPadTemplate; +use crate::{SpecificFormattedValue, SpecificFormattedValueIntrinsic}; use std::cell::RefCell; use std::mem; @@ -243,11 +243,11 @@ pub trait PadExtManual: 'static { ) -> Option; #[doc(alias = "gst_pad_peer_query_duration")] - fn peer_query_duration(&self) -> Option; + fn peer_query_duration(&self) -> Option; fn peer_query_duration_generic(&self, format: Format) -> Option; #[doc(alias = "gst_pad_peer_query_position")] - fn peer_query_position(&self) -> Option; + fn peer_query_position(&self) -> Option; fn peer_query_position_generic(&self, format: Format) -> Option; #[doc(alias = "gst_pad_query_convert")] @@ -262,11 +262,11 @@ pub trait PadExtManual: 'static { ) -> Option; #[doc(alias = "gst_pad_query_duration")] - fn query_duration(&self) -> Option; + fn query_duration(&self) -> Option; fn query_duration_generic(&self, format: Format) -> Option; #[doc(alias = "gst_pad_query_position")] - fn query_position(&self) -> Option; + fn query_position(&self) -> Option; fn query_position_generic(&self, format: Format) -> Option; #[doc(alias = "get_mode")] @@ -734,7 +734,7 @@ impl> PadExtManual for O { let ret = from_glib(ffi::gst_pad_peer_query_convert( self.as_ref().to_glib_none().0, src_val.format().into_glib(), - src_val.to_raw_value(), + src_val.into_raw_value(), U::default_format().into_glib(), dest_val.as_mut_ptr(), )); @@ -757,7 +757,7 @@ impl> PadExtManual for O { let ret = from_glib(ffi::gst_pad_peer_query_convert( self.as_ref().to_glib_none().0, src_val.format().into_glib(), - src_val.to_raw_value(), + src_val.into_raw_value(), dest_format.into_glib(), dest_val.as_mut_ptr(), )); @@ -772,16 +772,16 @@ impl> PadExtManual for O { } } - fn peer_query_duration(&self) -> Option { + fn peer_query_duration(&self) -> Option { unsafe { let mut duration = mem::MaybeUninit::uninit(); let ret = from_glib(ffi::gst_pad_peer_query_duration( self.as_ref().to_glib_none().0, - T::default_format().into_glib(), + T::FormattedValueType::default_format().into_glib(), duration.as_mut_ptr(), )); if ret { - Some(T::from_raw(T::default_format(), duration.assume_init())) + try_from_glib(duration.assume_init()).ok() } else { None } @@ -804,16 +804,16 @@ impl> PadExtManual for O { } } - fn peer_query_position(&self) -> Option { + fn peer_query_position(&self) -> Option { unsafe { let mut cur = mem::MaybeUninit::uninit(); let ret = from_glib(ffi::gst_pad_peer_query_position( self.as_ref().to_glib_none().0, - T::default_format().into_glib(), + T::FormattedValueType::default_format().into_glib(), cur.as_mut_ptr(), )); if ret { - Some(T::from_raw(T::default_format(), cur.assume_init())) + try_from_glib(cur.assume_init()).ok() } else { None } @@ -847,7 +847,7 @@ impl> PadExtManual for O { let ret = from_glib(ffi::gst_pad_query_convert( self.as_ref().to_glib_none().0, src_val.format().into_glib(), - src_val.to_raw_value(), + src_val.into_raw_value(), U::default_format().into_glib(), dest_val.as_mut_ptr(), )); @@ -886,16 +886,16 @@ impl> PadExtManual for O { } } - fn query_duration(&self) -> Option { + fn query_duration(&self) -> Option { unsafe { let mut duration = mem::MaybeUninit::uninit(); let ret = from_glib(ffi::gst_pad_query_duration( self.as_ref().to_glib_none().0, - T::default_format().into_glib(), + T::FormattedValueType::default_format().into_glib(), duration.as_mut_ptr(), )); if ret { - Some(T::from_raw(T::default_format(), duration.assume_init())) + try_from_glib(duration.assume_init()).ok() } else { None } @@ -918,16 +918,16 @@ impl> PadExtManual for O { } } - fn query_position(&self) -> Option { + fn query_position(&self) -> Option { unsafe { let mut cur = mem::MaybeUninit::uninit(); let ret = from_glib(ffi::gst_pad_query_position( self.as_ref().to_glib_none().0, - T::default_format().into_glib(), + T::FormattedValueType::default_format().into_glib(), cur.as_mut_ptr(), )); if ret { - Some(T::from_raw(T::default_format(), cur.assume_init())) + try_from_glib(cur.assume_init()).ok() } else { None } diff --git a/gstreamer/src/query.rs b/gstreamer/src/query.rs index 600caf36d..b258023d1 100644 --- a/gstreamer/src/query.rs +++ b/gstreamer/src/query.rs @@ -324,7 +324,7 @@ impl Default for Latency { impl Latency { #[doc(alias = "get_result")] - pub fn result(&self) -> (bool, crate::ClockTime, crate::ClockTime) { + pub fn result(&self) -> (bool, Option, Option) { unsafe { let mut live = mem::MaybeUninit::uninit(); let mut min = mem::MaybeUninit::uninit(); @@ -1428,6 +1428,7 @@ declare_concrete_query!(Other, T); #[cfg(test)] mod tests { use super::*; + use crate::ClockTime; use std::convert::TryInto; #[test] @@ -1439,10 +1440,10 @@ mod tests { match query.view_mut() { QueryView::Position(ref mut p) => { let pos = p.result(); - assert_eq!(pos.try_into(), Ok(crate::CLOCK_TIME_NONE)); - p.set(3 * crate::SECOND); + assert_eq!(pos.try_into(), Ok(ClockTime::NONE)); + p.set(Some(3 * ClockTime::SECOND)); let pos = p.result(); - assert_eq!(pos.try_into(), Ok(3 * crate::SECOND)); + assert_eq!(pos.try_into(), Ok(Some(3 * ClockTime::SECOND))); } _ => panic!("Wrong concrete Query in Query"), } @@ -1453,7 +1454,7 @@ mod tests { match query.view() { QueryView::Position(ref p) => { let pos = p.result(); - assert_eq!(pos.try_into(), Ok(3 * crate::SECOND)); + assert_eq!(pos.try_into(), Ok(Some(3 * ClockTime::SECOND))); unsafe { assert!(!p.as_mut_ptr().is_null()); } @@ -1464,7 +1465,7 @@ mod tests { let mut p = Position::new(crate::Format::Time); let pos = p.result(); - assert_eq!(pos.try_into(), Ok(crate::CLOCK_TIME_NONE)); + assert_eq!(pos.try_into(), Ok(ClockTime::NONE)); p.structure_mut().set("check_mut", &true); @@ -1494,12 +1495,12 @@ mod tests { let query = query.make_mut(); if let QueryView::Duration(d) = &mut query.view_mut() { - d.set(2 * crate::SECOND); + d.set(Some(2 * ClockTime::SECOND)); } if let QueryView::Duration(d) = &query.view() { let duration = d.result(); - assert_eq!(duration.try_into(), Ok(2 * crate::SECOND)); + assert_eq!(duration.try_into(), Ok(Some(2 * ClockTime::SECOND))); } } diff --git a/gstreamer/src/sample.rs b/gstreamer/src/sample.rs index 14175daf9..5925940cf 100644 --- a/gstreamer/src/sample.rs +++ b/gstreamer/src/sample.rs @@ -12,7 +12,7 @@ use crate::BufferRef; use crate::Caps; use crate::CapsRef; use crate::FormattedSegment; -use crate::FormattedValue; +use crate::FormattedValueIntrinsic; use crate::Segment; use crate::Structure; use crate::StructureRef; @@ -54,7 +54,7 @@ impl<'a> SampleBuilder<'a> { } } - pub fn segment(self, segment: &'a FormattedSegment) -> Self { + pub fn segment(self, segment: &'a FormattedSegment) -> Self { Self { segment: Some(segment.upcast_ref()), ..self diff --git a/gstreamer/src/sample_serde.rs b/gstreamer/src/sample_serde.rs index f51126331..440174202 100644 --- a/gstreamer/src/sample_serde.rs +++ b/gstreamer/src/sample_serde.rs @@ -96,10 +96,10 @@ mod tests { let mut buffer = Buffer::from_slice(vec![1, 2, 3, 4]); { let buffer = buffer.get_mut().unwrap(); - buffer.set_pts(1.into()); + buffer.set_pts(Some(ClockTime::NSECOND)); buffer.set_offset(0); buffer.set_offset_end(4); - buffer.set_duration(4.into()); + buffer.set_duration(Some(4 * ClockTime::NSECOND)); } let caps = Caps::builder("sample/caps") @@ -112,13 +112,13 @@ mod tests { segment.set_rate(1f64); segment.set_applied_rate(0.9f64); segment.set_format(Format::Time); - segment.set_base(GenericFormattedValue::Time(ClockTime::from_nseconds(123))); - segment.set_offset(GenericFormattedValue::Time(ClockTime::from_nseconds(42))); - segment.set_start(GenericFormattedValue::Time(ClockTime::from_nseconds(1024))); - segment.set_stop(GenericFormattedValue::Time(ClockTime::from_nseconds(2048))); - segment.set_time(GenericFormattedValue::Time(ClockTime::from_nseconds(1042))); - segment.set_position(GenericFormattedValue::Time(ClockTime::from_nseconds(256))); - segment.set_duration(GenericFormattedValue::Time(ClockTime::none())); + segment.set_base(GenericFormattedValue::from(ClockTime::from_nseconds(123))); + segment.set_offset(GenericFormattedValue::from(ClockTime::from_nseconds(42))); + segment.set_start(GenericFormattedValue::from(ClockTime::from_nseconds(1024))); + segment.set_stop(GenericFormattedValue::from(ClockTime::from_nseconds(2048))); + segment.set_time(GenericFormattedValue::from(ClockTime::from_nseconds(1042))); + segment.set_position(GenericFormattedValue::from(ClockTime::from_nseconds(256))); + segment.set_duration(GenericFormattedValue::from(ClockTime::NONE)); let info = Structure::builder("sample.info") .field("f3", &123i32) @@ -182,10 +182,10 @@ mod tests { let mut buffer = Buffer::from_slice(vec![1, 2, 3, 4]); { let buffer = buffer.get_mut().unwrap(); - buffer.set_pts(1.into()); + buffer.set_pts(Some(ClockTime::NSECOND)); buffer.set_offset(0); buffer.set_offset_end(4); - buffer.set_duration(4.into()); + buffer.set_duration(Some(4 * ClockTime::NSECOND)); } Sample::builder().buffer(&buffer).build() }; @@ -277,7 +277,7 @@ mod tests { )"#; let sample: Sample = ron::de::from_str(buffer_ron).unwrap(); let buffer = sample.buffer().unwrap(); - assert_eq!(buffer.pts(), 1.into()); + assert_eq!(buffer.pts(), Some(ClockTime::NSECOND)); assert_eq!(buffer.offset_end(), 4); { let data = buffer.map_readable().unwrap(); @@ -326,10 +326,10 @@ mod tests { let mut buffer = Buffer::from_slice(vec![1, 2, 3, 4]); { let buffer = buffer.get_mut().unwrap(); - buffer.set_pts(1.into()); + buffer.set_pts(Some(ClockTime::NSECOND)); buffer.set_offset(0); buffer.set_offset_end(4); - buffer.set_duration(4.into()); + buffer.set_duration(Some(4 * ClockTime::NSECOND)); } let caps = Caps::builder("sample/caps") @@ -342,13 +342,13 @@ mod tests { segment.set_rate(1f64); segment.set_applied_rate(0.9f64); segment.set_format(Format::Time); - segment.set_base(GenericFormattedValue::Time(ClockTime::from_nseconds(123))); - segment.set_offset(GenericFormattedValue::Time(ClockTime::from_nseconds(42))); - segment.set_start(GenericFormattedValue::Time(ClockTime::from_nseconds(1024))); - segment.set_stop(GenericFormattedValue::Time(ClockTime::from_nseconds(2048))); - segment.set_time(GenericFormattedValue::Time(ClockTime::from_nseconds(1042))); - segment.set_position(GenericFormattedValue::Time(ClockTime::from_nseconds(256))); - segment.set_duration(GenericFormattedValue::Time(ClockTime::none())); + segment.set_base(GenericFormattedValue::from(ClockTime::from_nseconds(123))); + segment.set_offset(GenericFormattedValue::from(ClockTime::from_nseconds(42))); + segment.set_start(GenericFormattedValue::from(ClockTime::from_nseconds(1024))); + segment.set_stop(GenericFormattedValue::from(ClockTime::from_nseconds(2048))); + segment.set_time(GenericFormattedValue::from(ClockTime::from_nseconds(1042))); + segment.set_position(GenericFormattedValue::from(ClockTime::from_nseconds(256))); + segment.set_duration(GenericFormattedValue::from(ClockTime::NONE)); let info = Structure::builder("sample.info") .field("f3", &123i32) @@ -364,7 +364,7 @@ mod tests { let sample_ser = ron::ser::to_string(&sample).unwrap(); let sample_de: Sample = ron::de::from_str(sample_ser.as_str()).unwrap(); let buffer_de = sample_de.buffer().unwrap(); - assert_eq!(buffer_de.pts(), 1.into()); + assert_eq!(buffer_de.pts(), Some(ClockTime::NSECOND)); assert_eq!(buffer_de.offset_end(), 4); { let data = buffer_de.map_readable().unwrap(); diff --git a/gstreamer/src/segment.rs b/gstreamer/src/segment.rs index 6ac0059ce..8bc6d414a 100644 --- a/gstreamer/src/segment.rs +++ b/gstreamer/src/segment.rs @@ -1,10 +1,10 @@ // Take a look at the license at the top of the repository in the LICENSE file. use crate::Format; -use crate::FormattedValue; use crate::GenericFormattedValue; use crate::SeekFlags; use crate::SeekType; +use crate::{FormattedValue, FormattedValueIntrinsic}; use glib::translate::*; use glib::StaticType; use std::fmt; @@ -15,7 +15,7 @@ use std::ptr; pub type Segment = FormattedSegment; #[repr(transparent)] #[doc(alias = "GstSegment")] -pub struct FormattedSegment(ffi::GstSegment, PhantomData); +pub struct FormattedSegment(ffi::GstSegment, PhantomData); impl Segment { pub fn reset_with_format(&mut self, format: Format) { @@ -28,16 +28,20 @@ impl Segment { self.0.format = format.into_glib(); } - pub fn downcast(self) -> Result, Self> { - if T::default_format() == Format::Undefined || T::default_format() == self.format() { + pub fn downcast(self) -> Result, Self> { + if T::FormattedValueType::default_format() == Format::Undefined + || T::FormattedValueType::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() { + pub fn downcast_ref(&self) -> Option<&FormattedSegment> { + if T::FormattedValueType::default_format() == Format::Undefined + || T::FormattedValueType::default_format() == self.format() + { Some(unsafe { &*(self as *const FormattedSegment as *const FormattedSegment) @@ -47,8 +51,10 @@ impl Segment { } } - pub fn downcast_mut(&mut self) -> Option<&mut FormattedSegment> { - if T::default_format() == Format::Undefined || T::default_format() == self.format() { + pub fn downcast_mut(&mut self) -> Option<&mut FormattedSegment> { + if T::FormattedValueType::default_format() == Format::Undefined + || T::FormattedValueType::default_format() == self.format() + { Some(unsafe { &mut *(self as *mut FormattedSegment as *mut FormattedSegment) @@ -59,12 +65,15 @@ impl Segment { } } -impl FormattedSegment { +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()); + ffi::gst_segment_init( + segment.as_mut_ptr(), + T::FormattedValueType::default_format().into_glib(), + ); segment.assume_init() }; FormattedSegment(segment, PhantomData) @@ -82,16 +91,23 @@ impl FormattedSegment { pub fn reset(&mut self) { unsafe { - ffi::gst_segment_init(&mut self.0, T::default_format().into_glib()); + ffi::gst_segment_init( + &mut self.0, + T::FormattedValueType::default_format().into_glib(), + ); } } #[doc(alias = "gst_segment_clip")] - pub fn clip>(&self, start: V, stop: V) -> Option<(T, T)> { + pub fn clip>( + &self, + start: V, + stop: V, + ) -> Option<(T::FormattedValueType, T::FormattedValueType)> { let start = start.into(); let stop = stop.into(); - if T::default_format() == Format::Undefined { + if T::FormattedValueType::default_format() == Format::Undefined { assert_eq!(self.format(), start.format()); assert_eq!(self.format(), stop.format()); } @@ -102,15 +118,15 @@ impl FormattedSegment { let ret = from_glib(ffi::gst_segment_clip( &self.0, start.format().into_glib(), - start.to_raw_value() as u64, - stop.to_raw_value() as u64, + 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::from_raw(self.format(), clip_start.assume_init() as i64), - T::from_raw(self.format(), clip_stop.assume_init() as i64), + T::FormattedValueType::from_raw(self.format(), clip_start.assume_init() as i64), + T::FormattedValueType::from_raw(self.format(), clip_stop.assume_init() as i64), )) } else { None @@ -120,7 +136,7 @@ impl FormattedSegment { #[allow(clippy::too_many_arguments)] #[doc(alias = "gst_segment_do_seek")] - pub fn do_seek>( + pub fn do_seek>( &mut self, rate: f64, flags: SeekFlags, @@ -133,7 +149,7 @@ impl FormattedSegment { let start = start.into(); let stop = stop.into(); - if T::default_format() == Format::Undefined { + if T::FormattedValueType::default_format() == Format::Undefined { assert_eq!(self.format(), start.format()); assert_eq!(self.format(), stop.format()); } @@ -146,9 +162,9 @@ impl FormattedSegment { self.format().into_glib(), flags.into_glib(), start_type.into_glib(), - start.to_raw_value() as u64, + start.into_raw_value() as u64, stop_type.into_glib(), - stop.to_raw_value() as u64, + stop.into_raw_value() as u64, update.as_mut_ptr(), )); if ret { @@ -174,30 +190,36 @@ impl FormattedSegment { } #[doc(alias = "gst_segment_position_from_running_time")] - pub fn position_from_running_time>(&self, running_time: V) -> T { + pub fn position_from_running_time>( + &self, + running_time: V, + ) -> T::FormattedValueType { let running_time = running_time.into(); - if T::default_format() == Format::Undefined { + if T::FormattedValueType::default_format() == Format::Undefined { assert_eq!(self.format(), running_time.format()); } unsafe { - T::from_raw( + T::FormattedValueType::from_raw( self.format(), ffi::gst_segment_position_from_running_time( &self.0, self.format().into_glib(), - running_time.to_raw_value() as u64, + running_time.into_raw_value() as u64, ) as i64, ) } } #[doc(alias = "gst_segment_position_from_running_time_full")] - pub fn position_from_running_time_full>(&self, running_time: V) -> (i32, T) { + pub fn position_from_running_time_full>( + &self, + running_time: V, + ) -> (i32, T::FormattedValueType) { let running_time = running_time.into(); - if T::default_format() == Format::Undefined { + if T::FormattedValueType::default_format() == Format::Undefined { assert_eq!(self.format(), running_time.format()); } @@ -206,41 +228,47 @@ impl FormattedSegment { let ret = ffi::gst_segment_position_from_running_time_full( &self.0, self.format().into_glib(), - running_time.to_raw_value() as u64, + running_time.into_raw_value() as u64, position.as_mut_ptr(), ); ( ret, - T::from_raw(self.format(), position.assume_init() as i64), + T::FormattedValueType::from_raw(self.format(), position.assume_init() as i64), ) } } #[doc(alias = "gst_segment_position_from_stream_time")] - pub fn position_from_stream_time>(&self, stream_time: V) -> T { + pub fn position_from_stream_time>( + &self, + stream_time: V, + ) -> T::FormattedValueType { let stream_time = stream_time.into(); - if T::default_format() == Format::Undefined { + if T::FormattedValueType::default_format() == Format::Undefined { assert_eq!(self.format(), stream_time.format()); } unsafe { - T::from_raw( + T::FormattedValueType::from_raw( self.format(), ffi::gst_segment_position_from_stream_time( &self.0, self.format().into_glib(), - stream_time.to_raw_value() as u64, + stream_time.into_raw_value() as u64, ) as i64, ) } } #[doc(alias = "gst_segment_position_from_stream_time_full")] - pub fn position_from_stream_time_full>(&self, stream_time: V) -> (i32, T) { + pub fn position_from_stream_time_full>( + &self, + stream_time: V, + ) -> (i32, T::FormattedValueType) { let stream_time = stream_time.into(); - if T::default_format() == Format::Undefined { + if T::FormattedValueType::default_format() == Format::Undefined { assert_eq!(self.format(), stream_time.format()); } @@ -249,21 +277,24 @@ impl FormattedSegment { let ret = ffi::gst_segment_position_from_stream_time_full( &self.0, self.format().into_glib(), - stream_time.to_raw_value() as u64, + stream_time.into_raw_value() as u64, position.as_mut_ptr(), ); ( ret, - T::from_raw(self.format(), position.assume_init() as i64), + T::FormattedValueType::from_raw(self.format(), position.assume_init() as i64), ) } } #[doc(alias = "gst_segment_set_running_time")] - pub fn set_running_time>(&mut self, running_time: V) -> Result<(), glib::BoolError> { + pub fn set_running_time>( + &mut self, + running_time: V, + ) -> Result<(), glib::BoolError> { let running_time = running_time.into(); - if T::default_format() == Format::Undefined { + if T::FormattedValueType::default_format() == Format::Undefined { assert_eq!(self.format(), running_time.format()); } @@ -272,7 +303,7 @@ impl FormattedSegment { ffi::gst_segment_set_running_time( &mut self.0, self.format().into_glib(), - running_time.to_raw_value() as u64, + running_time.into_raw_value() as u64, ), "Running time is not in the segment" ) @@ -280,30 +311,36 @@ impl FormattedSegment { } #[doc(alias = "gst_segment_to_running_time")] - pub fn to_running_time>(&self, position: V) -> T { + pub fn to_running_time>( + &self, + position: V, + ) -> T::FormattedValueType { let position = position.into(); - if T::default_format() == Format::Undefined { + if T::FormattedValueType::default_format() == Format::Undefined { assert_eq!(self.format(), position.format()); } unsafe { - T::from_raw( + T::FormattedValueType::from_raw( self.format(), ffi::gst_segment_to_running_time( &self.0, self.format().into_glib(), - position.to_raw_value() as u64, + position.into_raw_value() as u64, ) as i64, ) } } #[doc(alias = "gst_segment_to_running_time_full")] - pub fn to_running_time_full>(&self, position: V) -> (i32, T) { + pub fn to_running_time_full>( + &self, + position: V, + ) -> (i32, T::FormattedValueType) { let position = position.into(); - if T::default_format() == Format::Undefined { + if T::FormattedValueType::default_format() == Format::Undefined { assert_eq!(self.format(), position.format()); } @@ -312,41 +349,47 @@ impl FormattedSegment { let ret = ffi::gst_segment_to_running_time_full( &self.0, self.format().into_glib(), - position.to_raw_value() as u64, + position.into_raw_value() as u64, running_time.as_mut_ptr(), ); ( ret, - T::from_raw(self.format(), running_time.assume_init() as i64), + T::FormattedValueType::from_raw(self.format(), running_time.assume_init() as i64), ) } } #[doc(alias = "gst_segment_to_stream_time")] - pub fn to_stream_time>(&self, position: V) -> T { + pub fn to_stream_time>( + &self, + position: V, + ) -> T::FormattedValueType { let position = position.into(); - if T::default_format() == Format::Undefined { + if T::FormattedValueType::default_format() == Format::Undefined { assert_eq!(self.format(), position.format()); } unsafe { - T::from_raw( + T::FormattedValueType::from_raw( self.format(), ffi::gst_segment_to_stream_time( &self.0, self.format().into_glib(), - position.to_raw_value() as u64, + position.into_raw_value() as u64, ) as i64, ) } } #[doc(alias = "gst_segment_to_stream_time_full")] - pub fn to_stream_time_full>(&self, position: V) -> (i32, T) { + pub fn to_stream_time_full>( + &self, + position: V, + ) -> (i32, T::FormattedValueType) { let position = position.into(); - if T::default_format() == Format::Undefined { + if T::FormattedValueType::default_format() == Format::Undefined { assert_eq!(self.format(), position.format()); } @@ -355,12 +398,12 @@ impl FormattedSegment { let ret = ffi::gst_segment_to_stream_time_full( &self.0, self.format().into_glib(), - position.to_raw_value() as u64, + position.into_raw_value() as u64, stream_time.as_mut_ptr(), ); ( ret, - T::from_raw(self.format(), stream_time.assume_init() as i64), + T::FormattedValueType::from_raw(self.format(), stream_time.assume_init() as i64), ) } } @@ -402,112 +445,112 @@ impl FormattedSegment { } #[doc(alias = "get_base")] - pub fn base(&self) -> T { - unsafe { T::from_raw(self.format(), self.0.base as i64) } + pub fn base(&self) -> T::FormattedValueType { + unsafe { T::FormattedValueType::from_raw(self.format(), self.0.base as i64) } } - pub fn set_base>(&mut self, base: V) { + pub fn set_base>(&mut self, base: V) { let base = base.into(); - if T::default_format() == Format::Undefined { + if T::FormattedValueType::default_format() == Format::Undefined { assert_eq!(self.format(), base.format()); } - self.0.base = unsafe { base.to_raw_value() } as u64; + self.0.base = unsafe { base.into_raw_value() } as u64; } #[doc(alias = "get_offset")] - pub fn offset(&self) -> T { - unsafe { T::from_raw(self.format(), self.0.offset as i64) } + pub fn offset(&self) -> T::FormattedValueType { + unsafe { T::FormattedValueType::from_raw(self.format(), self.0.offset as i64) } } - pub fn set_offset>(&mut self, offset: V) { + pub fn set_offset>(&mut self, offset: V) { let offset = offset.into(); - if T::default_format() == Format::Undefined { + if T::FormattedValueType::default_format() == Format::Undefined { assert_eq!(self.format(), offset.format()); } - self.0.offset = unsafe { offset.to_raw_value() } as u64; + self.0.offset = unsafe { offset.into_raw_value() } as u64; } #[doc(alias = "get_start")] - pub fn start(&self) -> T { - unsafe { T::from_raw(self.format(), self.0.start as i64) } + pub fn start(&self) -> T::FormattedValueType { + unsafe { T::FormattedValueType::from_raw(self.format(), self.0.start as i64) } } - pub fn set_start>(&mut self, start: V) { + pub fn set_start>(&mut self, start: V) { let start = start.into(); - if T::default_format() == Format::Undefined { + if T::FormattedValueType::default_format() == Format::Undefined { assert_eq!(self.format(), start.format()); } - self.0.start = unsafe { start.to_raw_value() } as u64; + self.0.start = unsafe { start.into_raw_value() } as u64; } #[doc(alias = "get_stop")] - pub fn stop(&self) -> T { - unsafe { T::from_raw(self.format(), self.0.stop as i64) } + pub fn stop(&self) -> T::FormattedValueType { + unsafe { T::FormattedValueType::from_raw(self.format(), self.0.stop as i64) } } - pub fn set_stop>(&mut self, stop: V) { + pub fn set_stop>(&mut self, stop: V) { let stop = stop.into(); - if T::default_format() == Format::Undefined { + if T::FormattedValueType::default_format() == Format::Undefined { assert_eq!(self.format(), stop.format()); } - self.0.stop = unsafe { stop.to_raw_value() } as u64; + self.0.stop = unsafe { stop.into_raw_value() } as u64; } #[doc(alias = "get_time")] - pub fn time(&self) -> T { - unsafe { T::from_raw(self.format(), self.0.time as i64) } + pub fn time(&self) -> T::FormattedValueType { + unsafe { T::FormattedValueType::from_raw(self.format(), self.0.time as i64) } } - pub fn set_time>(&mut self, time: V) { + pub fn set_time>(&mut self, time: V) { let time = time.into(); - if T::default_format() == Format::Undefined { + if T::FormattedValueType::default_format() == Format::Undefined { assert_eq!(self.format(), time.format()); } - self.0.time = unsafe { time.to_raw_value() } as u64; + self.0.time = unsafe { time.into_raw_value() } as u64; } #[doc(alias = "get_position")] - pub fn position(&self) -> T { - unsafe { T::from_raw(self.format(), self.0.position as i64) } + pub fn position(&self) -> T::FormattedValueType { + unsafe { T::FormattedValueType::from_raw(self.format(), self.0.position as i64) } } - pub fn set_position>(&mut self, position: V) { + pub fn set_position>(&mut self, position: V) { let position = position.into(); - if T::default_format() == Format::Undefined { + if T::FormattedValueType::default_format() == Format::Undefined { assert_eq!(self.format(), position.format()); } - self.0.position = unsafe { position.to_raw_value() } as u64; + self.0.position = unsafe { position.into_raw_value() } as u64; } #[doc(alias = "get_duration")] - pub fn duration(&self) -> T { - unsafe { T::from_raw(self.format(), self.0.duration as i64) } + pub fn duration(&self) -> T::FormattedValueType { + unsafe { T::FormattedValueType::from_raw(self.format(), self.0.duration as i64) } } - pub fn set_duration>(&mut self, duration: V) { + pub fn set_duration>(&mut self, duration: V) { let duration = duration.into(); - if T::default_format() == Format::Undefined { + if T::FormattedValueType::default_format() == Format::Undefined { assert_eq!(self.format(), duration.format()); } - self.0.duration = unsafe { duration.to_raw_value() } as u64; + self.0.duration = unsafe { duration.into_raw_value() } as u64; } } -impl PartialEq for FormattedSegment { +impl PartialEq for FormattedSegment { #[inline] #[doc(alias = "gst_segment_is_equal")] fn eq(&self, other: &Self) -> bool { @@ -515,18 +558,18 @@ impl PartialEq for FormattedSegment { } } -impl Eq for FormattedSegment {} +impl Eq for FormattedSegment {} -unsafe impl Send for FormattedSegment {} -unsafe impl Sync for FormattedSegment {} +unsafe impl Send for FormattedSegment {} +unsafe impl Sync for FormattedSegment {} -impl Clone for FormattedSegment { +impl Clone for FormattedSegment { fn clone(&self) -> Self { unsafe { FormattedSegment(ptr::read(&self.0), PhantomData) } } } -impl AsRef for FormattedSegment { +impl AsRef for FormattedSegment { fn as_ref(&self) -> &Segment { unsafe { &*(self as *const FormattedSegment as *const FormattedSegment) @@ -534,8 +577,10 @@ impl AsRef for FormattedSegment { } } -impl fmt::Debug for 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 @@ -546,16 +591,16 @@ impl fmt::Debug for FormattedSegment { let segment = segment.downcast_ref::().unwrap(); f.debug_struct("Segment") .field("format", &Format::Time) - .field("start", &segment.start().to_string()) - .field("offset", &segment.offset().to_string()) - .field("stop", &segment.stop().to_string()) + .field("start", &segment.start().display().to_string()) + .field("offset", &segment.offset().display().to_string()) + .field("stop", &segment.stop().display().to_string()) .field("rate", &segment.rate()) .field("applied_rate", &segment.applied_rate()) .field("flags", &segment.flags()) - .field("time", &segment.time().to_string()) - .field("base", &segment.base().to_string()) - .field("position", &segment.position().to_string()) - .field("duration", &segment.duration().to_string()) + .field("time", &segment.time().display().to_string()) + .field("base", &segment.base().display().to_string()) + .field("position", &segment.position().display().to_string()) + .field("duration", &segment.duration().display().to_string()) .finish() } _ => f @@ -576,13 +621,13 @@ impl fmt::Debug for FormattedSegment { } } -impl Default for FormattedSegment { +impl Default for FormattedSegment { fn default() -> Self { Self::new() } } -impl glib::types::StaticType for FormattedSegment { +impl glib::types::StaticType for FormattedSegment { fn static_type() -> glib::types::Type { unsafe { glib::translate::from_glib(ffi::gst_segment_get_type()) } } @@ -605,7 +650,7 @@ unsafe impl<'a> glib::value::FromValue<'a> for Segment { } #[doc(hidden)] -impl glib::value::ToValue for FormattedSegment { +impl glib::value::ToValue for FormattedSegment { fn to_value(&self) -> glib::Value { let mut value = glib::Value::for_value_type::(); unsafe { @@ -623,7 +668,7 @@ impl glib::value::ToValue for FormattedSegment { } #[doc(hidden)] -impl glib::value::ToValueOptional for FormattedSegment { +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::(); @@ -638,12 +683,12 @@ impl glib::value::ToValueOptional for FormattedSegment { } #[doc(hidden)] #[doc(hidden)] -impl glib::translate::GlibPtrDefault for FormattedSegment { +impl glib::translate::GlibPtrDefault for FormattedSegment { type GlibType = *mut ffi::GstSegment; } #[doc(hidden)] -impl<'a, T: FormattedValue> glib::translate::ToGlibPtr<'a, *const ffi::GstSegment> +impl<'a, T: FormattedValueIntrinsic> glib::translate::ToGlibPtr<'a, *const ffi::GstSegment> for FormattedSegment { type Storage = &'a FormattedSegment; @@ -658,7 +703,7 @@ impl<'a, T: FormattedValue> glib::translate::ToGlibPtr<'a, *const ffi::GstSegmen } #[doc(hidden)] -impl<'a, T: FormattedValue> glib::translate::ToGlibPtrMut<'a, *mut ffi::GstSegment> +impl<'a, T: FormattedValueIntrinsic> glib::translate::ToGlibPtrMut<'a, *mut ffi::GstSegment> for FormattedSegment { type Storage = &'a mut FormattedSegment; diff --git a/gstreamer/src/segment_serde.rs b/gstreamer/src/segment_serde.rs index d933252ef..a37e65f46 100644 --- a/gstreamer/src/segment_serde.rs +++ b/gstreamer/src/segment_serde.rs @@ -7,10 +7,11 @@ use serde::ser::{Serialize, Serializer}; use crate::Format; use crate::FormattedSegment; use crate::FormattedValue; +use crate::FormattedValueIntrinsic; use crate::GenericFormattedValue; use crate::Segment; use crate::SegmentFlags; -use crate::SpecificFormattedValue; +use crate::SpecificFormattedValueIntrinsic; #[derive(serde::Serialize, serde::Deserialize)] struct FormattedSegmentSerde { @@ -27,7 +28,7 @@ struct FormattedSegmentSerde { duration: i64, } -impl Serialize for FormattedSegment { +impl Serialize for FormattedSegment { fn serialize(&self, serializer: S) -> Result { let fmt_seg = unsafe { FormattedSegmentSerde { @@ -35,13 +36,13 @@ impl Serialize for FormattedSegment { rate: self.rate(), applied_rate: self.applied_rate(), format: self.format(), - base: self.base().to_raw_value(), - offset: self.offset().to_raw_value(), - start: self.start().to_raw_value(), - stop: self.stop().to_raw_value(), - time: self.time().to_raw_value(), - position: self.position().to_raw_value(), - duration: self.duration().to_raw_value(), + base: self.base().into_raw_value(), + offset: self.offset().into_raw_value(), + start: self.start().into_raw_value(), + stop: self.stop().into_raw_value(), + time: self.time().into_raw_value(), + position: self.position().into_raw_value(), + duration: self.duration().into_raw_value(), } }; fmt_seg.serialize(serializer) @@ -91,7 +92,7 @@ impl<'de> Deserialize<'de> for Segment { } } -impl<'de, T: FormattedValue + SpecificFormattedValue> Deserialize<'de> for FormattedSegment { +impl<'de, T: SpecificFormattedValueIntrinsic> Deserialize<'de> for FormattedSegment { fn deserialize>(deserializer: D) -> Result { skip_assert_initialized!(); Segment::deserialize(deserializer).and_then(|segment| { @@ -99,7 +100,7 @@ impl<'de, T: FormattedValue + SpecificFormattedValue> Deserialize<'de> for Forma de::Error::custom(format!( "failed to convert segment with format {:?} to {:?}", segment.format(), - T::default_format(), + T::FormattedValueType::default_format(), )) }) }) @@ -123,13 +124,13 @@ mod tests { segment.set_rate(1f64); segment.set_applied_rate(0.9f64); segment.set_format(Format::Time); - segment.set_base(GenericFormattedValue::Time(ClockTime::from_nseconds(123))); - segment.set_offset(GenericFormattedValue::Time(ClockTime::from_nseconds(42))); - segment.set_start(GenericFormattedValue::Time(ClockTime::from_nseconds(1024))); - segment.set_stop(GenericFormattedValue::Time(ClockTime::from_nseconds(2048))); - segment.set_time(GenericFormattedValue::Time(ClockTime::from_nseconds(1042))); - segment.set_position(GenericFormattedValue::Time(ClockTime::from_nseconds(256))); - segment.set_duration(GenericFormattedValue::Time(ClockTime::none())); + segment.set_base(GenericFormattedValue::from(ClockTime::from_nseconds(123))); + segment.set_offset(GenericFormattedValue::from(ClockTime::from_nseconds(42))); + segment.set_start(GenericFormattedValue::from(ClockTime::from_nseconds(1024))); + segment.set_stop(GenericFormattedValue::from(ClockTime::from_nseconds(2048))); + segment.set_time(GenericFormattedValue::from(ClockTime::from_nseconds(1042))); + segment.set_position(GenericFormattedValue::from(ClockTime::from_nseconds(256))); + segment.set_duration(GenericFormattedValue::from(ClockTime::NONE)); let pretty_config = ron::ser::PrettyConfig::new().with_new_line("".to_string()); @@ -184,33 +185,37 @@ mod tests { assert!((segment.rate() - 1f64).abs() < std::f64::EPSILON); assert!((segment.applied_rate() - 0.9f64).abs() < std::f64::EPSILON); assert_eq!(segment.format(), Format::Time); + assert_eq!(segment.flags(), SegmentFlags::RESET | SegmentFlags::SEGMENT); + assert!((segment.rate() - 1f64).abs() < std::f64::EPSILON); + assert!((segment.applied_rate() - 0.9f64).abs() < std::f64::EPSILON); + assert_eq!(segment.format(), Format::Time); assert_eq!( segment.base(), - GenericFormattedValue::Time(ClockTime::from_nseconds(123)) + GenericFormattedValue::from(ClockTime::from_nseconds(123)), ); assert_eq!( segment.offset(), - GenericFormattedValue::Time(ClockTime::from_nseconds(42)) + GenericFormattedValue::from(ClockTime::from_nseconds(42)), ); assert_eq!( segment.start(), - GenericFormattedValue::Time(ClockTime::from_nseconds(1024)) + GenericFormattedValue::from(ClockTime::from_nseconds(1024)), ); assert_eq!( segment.stop(), - GenericFormattedValue::Time(ClockTime::from_nseconds(2048)) + GenericFormattedValue::from(ClockTime::from_nseconds(2048)), ); assert_eq!( segment.time(), - GenericFormattedValue::Time(ClockTime::from_nseconds(1042)) + GenericFormattedValue::from(ClockTime::from_nseconds(1042)), ); assert_eq!( segment.position(), - GenericFormattedValue::Time(ClockTime::from_nseconds(256)) + GenericFormattedValue::from(ClockTime::from_nseconds(256)), ); assert_eq!( segment.duration(), - GenericFormattedValue::Time(ClockTime::none()) + GenericFormattedValue::from(ClockTime::NONE), ); } @@ -244,13 +249,13 @@ mod tests { assert!((fmt_seg.rate() - 1f64).abs() < std::f64::EPSILON); assert!((fmt_seg.applied_rate() - 0.9f64).abs() < std::f64::EPSILON); assert_eq!(fmt_seg.format(), Format::Time); - assert_eq!(fmt_seg.base(), ClockTime::from_nseconds(123)); - assert_eq!(fmt_seg.offset(), ClockTime::from_nseconds(42)); - assert_eq!(fmt_seg.start(), ClockTime::from_nseconds(1024)); - assert_eq!(fmt_seg.stop(), ClockTime::from_nseconds(2048)); - assert_eq!(fmt_seg.time(), ClockTime::from_nseconds(1042)); - assert_eq!(fmt_seg.position(), ClockTime::from_nseconds(256)); - assert_eq!(fmt_seg.duration(), ClockTime::none()); + assert_eq!(fmt_seg.base(), Some(ClockTime::from_nseconds(123))); + assert_eq!(fmt_seg.offset(), Some(ClockTime::from_nseconds(42))); + assert_eq!(fmt_seg.start(), Some(ClockTime::from_nseconds(1024))); + assert_eq!(fmt_seg.stop(), Some(ClockTime::from_nseconds(2048))); + assert_eq!(fmt_seg.time(), Some(ClockTime::from_nseconds(1042))); + assert_eq!(fmt_seg.position(), Some(ClockTime::from_nseconds(256))); + assert_eq!(fmt_seg.duration(), ClockTime::NONE); } #[test] @@ -262,13 +267,13 @@ mod tests { segment.set_rate(1f64); segment.set_applied_rate(0.9f64); segment.set_format(Format::Time); - segment.set_base(GenericFormattedValue::Time(ClockTime::from_nseconds(123))); - segment.set_offset(GenericFormattedValue::Time(ClockTime::from_nseconds(42))); - segment.set_start(GenericFormattedValue::Time(ClockTime::from_nseconds(1024))); - segment.set_stop(GenericFormattedValue::Time(ClockTime::from_nseconds(2048))); - segment.set_time(GenericFormattedValue::Time(ClockTime::from_nseconds(1042))); - segment.set_position(GenericFormattedValue::Time(ClockTime::from_nseconds(256))); - segment.set_duration(GenericFormattedValue::Time(ClockTime::none())); + segment.set_base(GenericFormattedValue::from(ClockTime::from_nseconds(123))); + segment.set_offset(GenericFormattedValue::from(ClockTime::from_nseconds(42))); + segment.set_start(GenericFormattedValue::from(ClockTime::from_nseconds(1024))); + segment.set_stop(GenericFormattedValue::from(ClockTime::from_nseconds(2048))); + segment.set_time(GenericFormattedValue::from(ClockTime::from_nseconds(1042))); + segment.set_position(GenericFormattedValue::from(ClockTime::from_nseconds(256))); + segment.set_duration(GenericFormattedValue::from(ClockTime::NONE)); let segment_se = ron::ser::to_string(&segment).unwrap(); let segment_de: Segment = ron::de::from_str(segment_se.as_str()).unwrap(); diff --git a/gstreamer/src/subclass/clock.rs b/gstreamer/src/subclass/clock.rs index 892330bc2..bce62825e 100644 --- a/gstreamer/src/subclass/clock.rs +++ b/gstreamer/src/subclass/clock.rs @@ -18,15 +18,15 @@ pub trait ClockImpl: ClockImplExt + ObjectImpl + Send + Sync { clock: &Self::Type, old_resolution: ClockTime, new_resolution: ClockTime, - ) -> ClockTime { + ) -> Option { self.parent_change_resolution(clock, old_resolution, new_resolution) } - fn resolution(&self, clock: &Self::Type) -> ClockTime { + fn resolution(&self, clock: &Self::Type) -> Option { self.parent_resolution(clock) } - fn internal_time(&self, clock: &Self::Type) -> ClockTime { + fn internal_time(&self, clock: &Self::Type) -> Option { self.parent_internal_time(clock) } @@ -53,11 +53,11 @@ pub trait ClockImplExt: ObjectSubclass { clock: &Self::Type, old_resolution: ClockTime, new_resolution: ClockTime, - ) -> ClockTime; + ) -> Option; - fn parent_resolution(&self, clock: &Self::Type) -> ClockTime; + fn parent_resolution(&self, clock: &Self::Type) -> Option; - fn parent_internal_time(&self, clock: &Self::Type) -> ClockTime; + fn parent_internal_time(&self, clock: &Self::Type) -> Option; fn parent_wait( &self, @@ -85,7 +85,7 @@ impl ClockImplExt for T { clock: &Self::Type, old_resolution: ClockTime, new_resolution: ClockTime, - ) -> ClockTime { + ) -> Option { unsafe { let data = Self::type_data(); let parent_class = data.as_ref().parent_class() as *mut ffi::GstClockClass; @@ -102,7 +102,7 @@ impl ClockImplExt for T { } } - fn parent_resolution(&self, clock: &Self::Type) -> ClockTime { + fn parent_resolution(&self, clock: &Self::Type) -> Option { unsafe { let data = Self::type_data(); let parent_class = data.as_ref().parent_class() as *mut ffi::GstClockClass; @@ -116,7 +116,7 @@ impl ClockImplExt for T { } } - fn parent_internal_time(&self, clock: &Self::Type) -> ClockTime { + fn parent_internal_time(&self, clock: &Self::Type) -> Option { unsafe { let data = Self::type_data(); let parent_class = data.as_ref().parent_class() as *mut ffi::GstClockClass; @@ -254,12 +254,17 @@ unsafe extern "C" fn clock_change_resolution( let imp = instance.impl_(); let wrap: Borrowed = from_glib_borrow(ptr); - imp.change_resolution( - wrap.unsafe_cast_ref(), - from_glib(old_resolution), - from_glib(new_resolution), - ) - .into_glib() + let old_resolution = match from_glib(old_resolution) { + Some(old_resolution) => old_resolution, + None => return ffi::GST_CLOCK_TIME_NONE, + }; + let new_resolution = match from_glib(new_resolution) { + Some(new_resolution) => new_resolution, + None => return ffi::GST_CLOCK_TIME_NONE, + }; + + imp.change_resolution(wrap.unsafe_cast_ref(), old_resolution, new_resolution) + .into_glib() } unsafe extern "C" fn clock_get_resolution( diff --git a/gstreamer/src/subclass/element.rs b/gstreamer/src/subclass/element.rs index cdc305c66..1d0413e74 100644 --- a/gstreamer/src/subclass/element.rs +++ b/gstreamer/src/subclass/element.rs @@ -797,7 +797,7 @@ mod tests { pipeline.set_state(crate::State::Playing).unwrap(); let bus = pipeline.bus().unwrap(); - let eos = bus.timed_pop_filtered(crate::CLOCK_TIME_NONE, &[crate::MessageType::Eos]); + let eos = bus.timed_pop_filtered(crate::ClockTime::NONE, &[crate::MessageType::Eos]); assert!(eos.is_some()); pipeline.set_state(crate::State::Null).unwrap(); diff --git a/gstreamer/src/tags.rs b/gstreamer/src/tags.rs index 9d0af9d2b..a0ae09c6e 100644 --- a/gstreamer/src/tags.rs +++ b/gstreamer/src/tags.rs @@ -951,6 +951,7 @@ pub fn merge_strings_with_comma(src: &Value) -> Value { #[cfg(test)] mod tests { use super::*; + use crate::ClockTime; #[test] fn test_add() { @@ -961,7 +962,7 @@ mod tests { { let tags = tags.get_mut().unwrap(); tags.add::(&"some title", TagMergeMode::Append); - tags.add::<Duration>(&(crate::SECOND * 120), TagMergeMode::Append); + tags.add::<Duration>(&(ClockTime::SECOND * 120), TagMergeMode::Append); } assert_eq!( tags.to_string(), @@ -978,15 +979,19 @@ mod tests { { let tags = tags.get_mut().unwrap(); tags.add::<Title>(&"some title", TagMergeMode::Append); - tags.add::<Duration>(&(crate::SECOND * 120), TagMergeMode::Append); + tags.add::<Duration>(&(ClockTime::SECOND * 120), TagMergeMode::Append); } assert_eq!(tags.get::<Title>().unwrap().get(), "some title"); - assert_eq!(tags.get::<Duration>().unwrap().get(), crate::SECOND * 120); + assert_eq!( + tags.get::<Duration>().unwrap().get(), + ClockTime::SECOND * 120, + ); + assert_eq!(tags.index::<Title>(0).unwrap().get(), "some title"); assert_eq!(tags.index::<Title>(0).unwrap().get(), "some title"); assert_eq!( tags.index::<Duration>(0).unwrap().get(), - crate::SECOND * 120 + ClockTime::SECOND * 120, ); } @@ -1018,7 +1023,11 @@ mod tests { .add_generic(&TAG_TITLE, "second title", TagMergeMode::Append) .is_ok()); assert!(tags - .add_generic(&TAG_DURATION, crate::SECOND * 120, TagMergeMode::Append) + .add_generic( + &TAG_DURATION, + &(ClockTime::SECOND * 120), + TagMergeMode::Append + ) .is_ok()); assert!(tags .add_generic(&TAG_TITLE, "third title", TagMergeMode::Append) @@ -1044,7 +1053,7 @@ mod tests { ); assert_eq!( tags.index_generic(&TAG_DURATION, 0).unwrap().get(), - Ok(crate::SECOND * 120) + Ok(Some(ClockTime::SECOND * 120)) ); assert_eq!( tags.index_generic(&TAG_TITLE, 2).unwrap().get(), @@ -1090,7 +1099,7 @@ mod tests { let (tag_name, mut tag_iter) = tag_list_iter.next().unwrap(); assert_eq!(tag_name, *TAG_DURATION); let first_duration = tag_iter.next().unwrap(); - assert_eq!(first_duration.get(), Ok(crate::SECOND * 120)); + assert_eq!(first_duration.get(), Ok(Some(ClockTime::SECOND * 120))); assert!(tag_iter.next().is_none()); // Iter @@ -1106,7 +1115,7 @@ mod tests { let (tag_name, tag_value) = tag_list_iter.next().unwrap(); assert_eq!(tag_name, *TAG_DURATION); - assert_eq!(tag_value.get(), Ok(crate::SECOND * 120)); + assert_eq!(tag_value.get(), Ok(Some(ClockTime::SECOND * 120))); assert!(tag_iter.next().is_none()); } diff --git a/gstreamer/src/tags_serde.rs b/gstreamer/src/tags_serde.rs index e86412a84..28798a376 100644 --- a/gstreamer/src/tags_serde.rs +++ b/gstreamer/src/tags_serde.rs @@ -311,6 +311,7 @@ impl<'de> Deserialize<'de> for TagList { mod tests { use crate::tags::*; use crate::Buffer; + use crate::ClockTime; use crate::Sample; use crate::TagMergeMode; use crate::TagScope; @@ -325,7 +326,7 @@ mod tests { let tags = tags.get_mut().unwrap(); tags.add::<Title>(&"a title", TagMergeMode::Append); // String tags.add::<Title>(&"another title", TagMergeMode::Append); // String - tags.add::<Duration>(&(crate::SECOND * 120), TagMergeMode::Append); // u64 + tags.add::<Duration>(&(ClockTime::SECOND * 120), TagMergeMode::Append); // u64 tags.add::<Bitrate>(&96_000, TagMergeMode::Append); // u32 tags.add::<TrackGain>(&1f64, TagMergeMode::Append); // f64 tags.add::<Date>( @@ -465,9 +466,10 @@ mod tests { assert_eq!(tags.index::<Title>(0).unwrap().get(), "a title"); assert_eq!(tags.index::<Title>(1).unwrap().get(), "another title"); + assert_eq!(tags.index::<Title>(1).unwrap().get(), "another title"); assert_eq!( tags.index::<Duration>(0).unwrap().get(), - crate::SECOND * 120 + 120 * ClockTime::SECOND, ); assert_eq!(tags.index::<Bitrate>(0).unwrap().get(), 96_000); assert!((tags.index::<TrackGain>(0).unwrap().get() - 1f64).abs() < std::f64::EPSILON); @@ -534,7 +536,7 @@ mod tests { tags.set_scope(TagScope::Global); tags.add::<Title>(&"a title", TagMergeMode::Append); // String tags.add::<Title>(&"another title", TagMergeMode::Append); // String - tags.add::<Duration>(&(crate::SECOND * 120), TagMergeMode::Append); // u64 + tags.add::<Duration>(&(ClockTime::SECOND * 120), TagMergeMode::Append); // u64 tags.add::<Bitrate>(&96_000, TagMergeMode::Append); // u32 tags.add::<TrackGain>(&1f64, TagMergeMode::Append); // f64 tags.add::<Date>( diff --git a/gstreamer/src/utils.rs b/gstreamer/src/utils.rs index de52dc90c..a342a4ad9 100644 --- a/gstreamer/src/utils.rs +++ b/gstreamer/src/utils.rs @@ -25,3 +25,11 @@ impl<'a> Drop for MutexGuard<'a> { } } } + +// rustdoc-stripper-ignore-next +/// Trait that allows accessing `Display` implementation on types external to this crate. +pub trait Displayable { + type DisplayImpl: std::fmt::Display; + + fn display(self) -> Self::DisplayImpl; +} diff --git a/tutorials/src/bin/basic-tutorial-13.rs b/tutorials/src/bin/basic-tutorial-13.rs index 0c14d5ea1..0d5b010b1 100644 --- a/tutorials/src/bin/basic-tutorial-13.rs +++ b/tutorials/src/bin/basic-tutorial-13.rs @@ -26,7 +26,7 @@ enum Command { fn send_seek_event(pipeline: &Element, rate: f64) -> bool { // Obtain the current position, needed for the seek event - let position = match pipeline.query_position::<gst::ClockTime>() { + let position = match pipeline.query_position() { Some(pos) => pos, None => { eprintln!("Unable to retrieve current position...\r"); @@ -42,7 +42,7 @@ fn send_seek_event(pipeline: &Element, rate: f64) -> bool { SeekType::Set, position, SeekType::End, - gst::ClockTime::from(0), + gst::ClockTime::ZERO, ) } else { Seek::new( diff --git a/tutorials/src/bin/basic-tutorial-4.rs b/tutorials/src/bin/basic-tutorial-4.rs index 1c8e65356..5a4a598f5 100644 --- a/tutorials/src/bin/basic-tutorial-4.rs +++ b/tutorials/src/bin/basic-tutorial-4.rs @@ -60,11 +60,8 @@ fn tutorial_main() { .expect("Could not query current position."); // If we didn't know it yet, query the stream duration - if custom_data.duration == gst::CLOCK_TIME_NONE { - custom_data.duration = custom_data - .playbin - .query_duration() - .expect("Could not query current duration.") + if custom_data.duration == gst::ClockTime::NONE { + custom_data.duration = custom_data.playbin.query_duration(); } // Print current position and total duration @@ -73,7 +70,7 @@ fn tutorial_main() { if custom_data.seek_enabled && !custom_data.seek_done - && position > 10 * gst::SECOND + && position > 10 * gst::ClockTime::SECOND { println!("\nReached 10s, performing seek..."); custom_data diff --git a/tutorials/src/bin/basic-tutorial-5.rs b/tutorials/src/bin/basic-tutorial-5.rs index 593b65346..50ab9c301 100644 --- a/tutorials/src/bin/basic-tutorial-5.rs +++ b/tutorials/src/bin/basic-tutorial-5.rs @@ -140,15 +140,13 @@ mod tutorial5 { let lslider = &lslider; if let Some(dur) = pipeline.query_duration::<gst::ClockTime>() { - let seconds = dur / gst::SECOND; - lslider.set_range(0.0, seconds.map(|v| v as f64).unwrap_or(0.0)); - } + lslider.set_range(0.0, dur.seconds() as f64); - if let Some(pos) = pipeline.query_position::<gst::ClockTime>() { - let seconds = pos / gst::SECOND; - lslider.block_signal(&slider_update_signal_id); - lslider.set_value(seconds.map(|v| v as f64).unwrap_or(0.0)); - lslider.unblock_signal(&slider_update_signal_id); + if let Some(pos) = pipeline.query_position::<gst::ClockTime>() { + lslider.block_signal(&slider_update_signal_id); + lslider.set_value(pos.seconds() as f64); + lslider.unblock_signal(&slider_update_signal_id); + } } Continue(true) diff --git a/tutorials/src/bin/basic-tutorial-9.rs b/tutorials/src/bin/basic-tutorial-9.rs index 50b85c4e3..ddc32fb1e 100644 --- a/tutorials/src/bin/basic-tutorial-9.rs +++ b/tutorials/src/bin/basic-tutorial-9.rs @@ -107,7 +107,7 @@ fn on_discovered( return; } - println!("Duration: {}", discoverer_info.duration()); + println!("Duration: {}", discoverer_info.duration().display()); if let Some(tags) = discoverer_info.tags() { println!("Tags:"); diff --git a/tutorials/src/bin/playback-tutorial-4.rs b/tutorials/src/bin/playback-tutorial-4.rs index 073a94d36..e1a5aa04e 100644 --- a/tutorials/src/bin/playback-tutorial-4.rs +++ b/tutorials/src/bin/playback-tutorial-4.rs @@ -153,7 +153,7 @@ fn tutorial_main() -> Result<(), Error> { if let Some(position) = pipeline.query_position::<gst::ClockTime>() { if let Some(duration) = pipeline.query_duration::<gst::ClockTime>() { let current_progress = - GRAPH_LENGTH as u64 * position.seconds().unwrap() / duration.seconds().unwrap(); + GRAPH_LENGTH as u64 * position.seconds() / duration.seconds(); let buffering_level = buffering_level.lock().unwrap(); graph[current_progress as usize] = if *buffering_level < 100 { b'X' } else { b'>' }; }