diff --git a/gstreamer/src/subclass/device_provider.rs b/gstreamer/src/subclass/device_provider.rs new file mode 100644 index 000000000..266580923 --- /dev/null +++ b/gstreamer/src/subclass/device_provider.rs @@ -0,0 +1,174 @@ +// 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 glib_sys; +use gst_sys; + +use glib::translate::*; + +use glib::subclass::prelude::*; + +use Device; +use DeviceProvider; +use DeviceProviderClass; +use LoggableError; + +pub trait DeviceProviderImpl: DeviceProviderImplExt + ObjectImpl + Send + Sync + 'static { + fn probe(&self, device_provider: &DeviceProvider) -> Vec { + self.parent_probe(device_provider) + } + + fn start(&self, device_provider: &DeviceProvider) -> Result<(), LoggableError> { + self.parent_start(device_provider) + } + + fn stop(&self, device_provider: &DeviceProvider) { + self.parent_stop(device_provider) + } +} + +pub trait DeviceProviderImplExt { + fn parent_probe(&self, device_provider: &DeviceProvider) -> Vec; + + fn parent_start(&self, device_provider: &DeviceProvider) -> Result<(), LoggableError>; + + fn parent_stop(&self, device_provider: &DeviceProvider); +} + +impl DeviceProviderImplExt for T { + fn parent_probe(&self, device_provider: &DeviceProvider) -> Vec { + unsafe { + let data = self.get_type_data(); + let parent_class = + data.as_ref().get_parent_class() as *mut gst_sys::GstDeviceProviderClass; + if let Some(f) = (*parent_class).probe { + FromGlibPtrContainer::from_glib_full(f(device_provider.to_glib_none().0)) + } else { + Vec::new() + } + } + } + + fn parent_start(&self, device_provider: &DeviceProvider) -> Result<(), LoggableError> { + unsafe { + let data = self.get_type_data(); + let parent_class = + data.as_ref().get_parent_class() as *mut gst_sys::GstDeviceProviderClass; + let f = (*parent_class).start.ok_or_else(|| { + gst_loggable_error!(::CAT_RUST, "Parent function `start` is not defined") + })?; + gst_result_from_gboolean!( + f(device_provider.to_glib_none().0), + ::CAT_RUST, + "Failed to start the device provider using the parent function" + ) + } + } + + fn parent_stop(&self, device_provider: &DeviceProvider) { + unsafe { + let data = self.get_type_data(); + let parent_class = + data.as_ref().get_parent_class() as *mut gst_sys::GstDeviceProviderClass; + if let Some(f) = (*parent_class).stop { + f(device_provider.to_glib_none().0); + } + } + } +} + +pub unsafe trait DeviceProviderClassSubclassExt: Sized + 'static { + fn set_metadata( + &mut self, + long_name: &str, + classification: &str, + description: &str, + author: &str, + ) { + unsafe { + gst_sys::gst_device_provider_class_set_metadata( + self as *mut Self as *mut gst_sys::GstDeviceProviderClass, + long_name.to_glib_none().0, + classification.to_glib_none().0, + description.to_glib_none().0, + author.to_glib_none().0, + ); + } + } + + fn add_metadata(&mut self, key: &str, value: &str) { + unsafe { + gst_sys::gst_device_provider_class_add_metadata( + self as *mut Self as *mut gst_sys::GstDeviceProviderClass, + key.to_glib_none().0, + value.to_glib_none().0, + ); + } + } +} + +unsafe impl DeviceProviderClassSubclassExt for DeviceProviderClass {} + +unsafe impl IsSubclassable for DeviceProviderClass { + fn override_vfuncs(&mut self) { + >::override_vfuncs(self); + unsafe { + let klass = &mut *(self as *mut Self as *mut gst_sys::GstDeviceProviderClass); + klass.probe = Some(device_provider_probe::); + klass.start = Some(device_provider_start::); + klass.stop = Some(device_provider_stop::); + } + } +} + +unsafe extern "C" fn device_provider_probe( + ptr: *mut gst_sys::GstDeviceProvider, +) -> *mut glib_sys::GList +where + T: DeviceProviderImpl, +{ + glib_floating_reference_guard!(ptr); + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: DeviceProvider = from_glib_borrow(ptr); + + imp.probe(&wrap).to_glib_full() +} + +unsafe extern "C" fn device_provider_start( + ptr: *mut gst_sys::GstDeviceProvider, +) -> glib_sys::gboolean +where + T: DeviceProviderImpl, +{ + glib_floating_reference_guard!(ptr); + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: DeviceProvider = from_glib_borrow(ptr); + + match imp.start(&wrap) { + Ok(()) => true, + Err(err) => { + err.log_with_object(&wrap); + false + } + } + .to_glib() +} + +unsafe extern "C" fn device_provider_stop(ptr: *mut gst_sys::GstDeviceProvider) +where + T: DeviceProviderImpl, +{ + glib_floating_reference_guard!(ptr); + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: DeviceProvider = from_glib_borrow(ptr); + + imp.stop(&wrap); +} diff --git a/gstreamer/src/subclass/mod.rs b/gstreamer/src/subclass/mod.rs index 4ebdeaea5..4858f8cb1 100644 --- a/gstreamer/src/subclass/mod.rs +++ b/gstreamer/src/subclass/mod.rs @@ -29,6 +29,7 @@ pub mod pad; pub mod pipeline; pub mod device; +pub mod device_provider; pub mod uri_handler; @@ -36,6 +37,9 @@ pub mod prelude { pub use super::bin::{BinImpl, BinImplExt}; pub use super::child_proxy::ChildProxyImpl; pub use super::device::{DeviceImpl, DeviceImplExt}; + pub use super::device_provider::{ + DeviceProviderClassSubclassExt, DeviceProviderImpl, DeviceProviderImplExt, + }; pub use super::element::{ElementClassSubclassExt, ElementImpl, ElementImplExt}; pub use super::ghost_pad::GhostPadImpl; pub use super::pad::{PadImpl, PadImplExt};