diff --git a/gstreamer/src/subclass/clock.rs b/gstreamer/src/subclass/clock.rs new file mode 100644 index 000000000..3153c1f84 --- /dev/null +++ b/gstreamer/src/subclass/clock.rs @@ -0,0 +1,305 @@ +// Copyright (C) 2019 Sebastian Dröge +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use gst_sys; + +use glib; +use glib::translate::*; + +use glib::subclass::prelude::*; + +use Clock; +use ClockClass; +use ClockError; +use ClockId; +use ClockReturn; +use ClockSuccess; +use ClockTime; +use ClockTimeDiff; + +pub trait ClockImpl: ClockImplExt + ObjectImpl + Send + Sync + 'static { + fn change_resolution( + &self, + clock: &Clock, + old_resolution: ClockTime, + new_resolution: ClockTime, + ) -> ClockTime { + self.parent_change_resolution(clock, old_resolution, new_resolution) + } + + fn get_resolution(&self, clock: &Clock) -> ClockTime { + self.parent_get_resolution(clock) + } + + fn get_internal_time(&self, clock: &Clock) -> ClockTime { + self.parent_get_internal_time(clock) + } + + fn wait( + &self, + clock: &Clock, + id: &ClockId, + ) -> (Result, ClockTimeDiff) { + self.parent_wait(clock, id) + } + + fn wait_async(&self, clock: &Clock, id: &ClockId) -> Result { + self.parent_wait_async(clock, id) + } + + fn unschedule(&self, clock: &Clock, id: &ClockId) { + self.parent_unschedule(clock, id) + } +} + +pub trait ClockImplExt { + fn parent_change_resolution( + &self, + clock: &Clock, + old_resolution: ClockTime, + new_resolution: ClockTime, + ) -> ClockTime; + + fn parent_get_resolution(&self, clock: &Clock) -> ClockTime; + + fn parent_get_internal_time(&self, clock: &Clock) -> ClockTime; + + fn parent_wait( + &self, + clock: &Clock, + id: &ClockId, + ) -> (Result, ClockTimeDiff); + + fn parent_wait_async(&self, clock: &Clock, id: &ClockId) -> Result; + + fn parent_unschedule(&self, clock: &Clock, id: &ClockId); +} + +impl ClockImplExt for T { + fn parent_change_resolution( + &self, + clock: &Clock, + old_resolution: ClockTime, + new_resolution: ClockTime, + ) -> ClockTime { + unsafe { + let data = self.get_type_data(); + let parent_class = data.as_ref().get_parent_class() as *mut gst_sys::GstClockClass; + + if let Some(func) = (*parent_class).change_resolution { + from_glib(func( + clock.to_glib_none().0, + old_resolution.to_glib(), + new_resolution.to_glib(), + )) + } else { + self.get_resolution(clock) + } + } + } + + fn parent_get_resolution(&self, clock: &Clock) -> ClockTime { + unsafe { + let data = self.get_type_data(); + let parent_class = data.as_ref().get_parent_class() as *mut gst_sys::GstClockClass; + + from_glib( + (*parent_class) + .get_resolution + .map(|f| f(clock.to_glib_none().0)) + .unwrap_or(1), + ) + } + } + + fn parent_get_internal_time(&self, clock: &Clock) -> ClockTime { + unsafe { + let data = self.get_type_data(); + let parent_class = data.as_ref().get_parent_class() as *mut gst_sys::GstClockClass; + + from_glib( + (*parent_class) + .get_internal_time + .map(|f| f(clock.to_glib_none().0)) + .unwrap_or(0), + ) + } + } + + fn parent_wait( + &self, + clock: &Clock, + id: &ClockId, + ) -> (Result, ClockTimeDiff) { + unsafe { + let data = self.get_type_data(); + let parent_class = data.as_ref().get_parent_class() as *mut gst_sys::GstClockClass; + let mut jitter = 0; + + ( + ClockReturn::from_glib( + (*parent_class) + .wait + .map(|f| { + f( + clock.to_glib_none().0, + id.to_glib_none().0 as *mut gst_sys::GstClockEntry, + &mut jitter, + ) + }) + .unwrap_or(gst_sys::GST_CLOCK_UNSUPPORTED), + ) + .into_result(), + jitter, + ) + } + } + + fn parent_wait_async(&self, clock: &Clock, id: &ClockId) -> Result { + unsafe { + let data = self.get_type_data(); + let parent_class = data.as_ref().get_parent_class() as *mut gst_sys::GstClockClass; + ClockReturn::from_glib( + (*parent_class) + .wait_async + .map(|f| { + f( + clock.to_glib_none().0, + id.to_glib_none().0 as *mut gst_sys::GstClockEntry, + ) + }) + .unwrap_or(gst_sys::GST_CLOCK_UNSUPPORTED), + ) + .into_result() + } + } + + fn parent_unschedule(&self, clock: &Clock, id: &ClockId) { + unsafe { + let data = self.get_type_data(); + let parent_class = data.as_ref().get_parent_class() as *mut gst_sys::GstClockClass; + if let Some(func) = (*parent_class).unschedule { + func( + clock.to_glib_none().0, + id.to_glib_none().0 as *mut gst_sys::GstClockEntry, + ); + } + } + } +} + +unsafe impl IsSubclassable for ClockClass { + fn override_vfuncs(&mut self) { + >::override_vfuncs(self); + + unsafe { + let klass = &mut *(self as *mut Self as *mut gst_sys::GstClockClass); + klass.change_resolution = Some(clock_change_resolution::); + klass.get_resolution = Some(clock_get_resolution::); + klass.get_internal_time = Some(clock_get_internal_time::); + klass.wait = Some(clock_wait::); + klass.wait_async = Some(clock_wait_async::); + klass.unschedule = Some(clock_unschedule::); + } + } +} + +unsafe extern "C" fn clock_change_resolution( + ptr: *mut gst_sys::GstClock, + old_resolution: gst_sys::GstClockTime, + new_resolution: gst_sys::GstClockTime, +) -> gst_sys::GstClockTime +where + T: ClockImpl, +{ + glib_floating_reference_guard!(ptr); + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: Clock = from_glib_borrow(ptr); + + imp.change_resolution(&wrap, from_glib(old_resolution), from_glib(new_resolution)) + .to_glib() +} + +unsafe extern "C" fn clock_get_resolution( + ptr: *mut gst_sys::GstClock, +) -> gst_sys::GstClockTime +where + T: ClockImpl, +{ + glib_floating_reference_guard!(ptr); + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: Clock = from_glib_borrow(ptr); + + imp.get_resolution(&wrap).to_glib() +} + +unsafe extern "C" fn clock_get_internal_time( + ptr: *mut gst_sys::GstClock, +) -> gst_sys::GstClockTime +where + T: ClockImpl, +{ + glib_floating_reference_guard!(ptr); + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: Clock = from_glib_borrow(ptr); + + imp.get_internal_time(&wrap).to_glib() +} + +unsafe extern "C" fn clock_wait( + ptr: *mut gst_sys::GstClock, + id: *mut gst_sys::GstClockEntry, + jitter: *mut gst_sys::GstClockTimeDiff, +) -> gst_sys::GstClockReturn +where + T: ClockImpl, +{ + glib_floating_reference_guard!(ptr); + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: Clock = from_glib_borrow(ptr); + + let (res, j) = imp.wait(&wrap, &from_glib_borrow(id as gst_sys::GstClockID)); + if !jitter.is_null() { + *jitter = j; + } + + ClockReturn::from(res).to_glib() +} + +unsafe extern "C" fn clock_wait_async( + ptr: *mut gst_sys::GstClock, + id: *mut gst_sys::GstClockEntry, +) -> gst_sys::GstClockReturn +where + T: ClockImpl, +{ + glib_floating_reference_guard!(ptr); + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: Clock = from_glib_borrow(ptr); + + ClockReturn::from(imp.wait_async(&wrap, &from_glib_borrow(id as gst_sys::GstClockID))).to_glib() +} + +unsafe extern "C" fn clock_unschedule( + ptr: *mut gst_sys::GstClock, + id: *mut gst_sys::GstClockEntry, +) where + T: ClockImpl, +{ + glib_floating_reference_guard!(ptr); + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: Clock = from_glib_borrow(ptr); + + imp.unschedule(&wrap, &from_glib_borrow(id as gst_sys::GstClockID)); +} diff --git a/gstreamer/src/subclass/mod.rs b/gstreamer/src/subclass/mod.rs index c54894abc..0b8b7305c 100644 --- a/gstreamer/src/subclass/mod.rs +++ b/gstreamer/src/subclass/mod.rs @@ -31,6 +31,8 @@ pub mod pipeline; pub mod device; pub mod device_provider; +pub mod clock; + pub mod preset; pub mod tag_setter; pub mod uri_handler; @@ -38,6 +40,7 @@ pub mod uri_handler; pub mod prelude { pub use super::bin::{BinImpl, BinImplExt}; pub use super::child_proxy::ChildProxyImpl; + pub use super::clock::{ClockImpl, ClockImplExt}; pub use super::device::{DeviceImpl, DeviceImplExt}; pub use super::device_provider::{ DeviceProviderClassSubclassExt, DeviceProviderImpl, DeviceProviderImplExt,