// Take a look at the license at the top of the repository in the LICENSE file. use glib::prelude::*; use glib::subclass::prelude::*; use glib::translate::*; use gst::subclass::prelude::*; use std::mem; use std::ptr; use crate::BaseSrc; #[derive(Debug)] pub enum CreateSuccess { FilledBuffer, NewBuffer(gst::Buffer), } pub trait BaseSrcImpl: BaseSrcImplExt + ElementImpl { fn start(&self, element: &Self::Type) -> Result<(), gst::ErrorMessage> { self.parent_start(element) } fn stop(&self, element: &Self::Type) -> Result<(), gst::ErrorMessage> { self.parent_stop(element) } fn is_seekable(&self, element: &Self::Type) -> bool { self.parent_is_seekable(element) } fn get_size(&self, element: &Self::Type) -> Option { self.parent_get_size(element) } fn get_times( &self, element: &Self::Type, buffer: &gst::BufferRef, ) -> (gst::ClockTime, gst::ClockTime) { self.parent_get_times(element, buffer) } fn fill( &self, element: &Self::Type, offset: u64, length: u32, buffer: &mut gst::BufferRef, ) -> Result { self.parent_fill(element, offset, length, buffer) } fn alloc( &self, element: &Self::Type, offset: u64, length: u32, ) -> Result { self.parent_alloc(element, offset, length) } fn create( &self, element: &Self::Type, offset: u64, buffer: Option<&mut gst::BufferRef>, length: u32, ) -> Result { self.parent_create(element, offset, buffer, length) } fn do_seek(&self, element: &Self::Type, segment: &mut gst::Segment) -> bool { self.parent_do_seek(element, segment) } fn query(&self, element: &Self::Type, query: &mut gst::QueryRef) -> bool { BaseSrcImplExt::parent_query(self, element, query) } fn event(&self, element: &Self::Type, event: &gst::Event) -> bool { self.parent_event(element, event) } fn get_caps(&self, element: &Self::Type, filter: Option<&gst::Caps>) -> Option { self.parent_get_caps(element, filter) } fn negotiate(&self, element: &Self::Type) -> Result<(), gst::LoggableError> { self.parent_negotiate(element) } fn set_caps(&self, element: &Self::Type, caps: &gst::Caps) -> Result<(), gst::LoggableError> { self.parent_set_caps(element, caps) } fn fixate(&self, element: &Self::Type, caps: gst::Caps) -> gst::Caps { self.parent_fixate(element, caps) } fn unlock(&self, element: &Self::Type) -> Result<(), gst::ErrorMessage> { self.parent_unlock(element) } fn unlock_stop(&self, element: &Self::Type) -> Result<(), gst::ErrorMessage> { self.parent_unlock_stop(element) } } pub trait BaseSrcImplExt: ObjectSubclass { fn parent_start(&self, element: &Self::Type) -> Result<(), gst::ErrorMessage>; fn parent_stop(&self, element: &Self::Type) -> Result<(), gst::ErrorMessage>; fn parent_is_seekable(&self, element: &Self::Type) -> bool; fn parent_get_size(&self, element: &Self::Type) -> Option; fn parent_get_times( &self, element: &Self::Type, buffer: &gst::BufferRef, ) -> (gst::ClockTime, gst::ClockTime); fn parent_fill( &self, element: &Self::Type, offset: u64, length: u32, buffer: &mut gst::BufferRef, ) -> Result; fn parent_alloc( &self, element: &Self::Type, offset: u64, length: u32, ) -> Result; fn parent_create( &self, element: &Self::Type, offset: u64, buffer: Option<&mut gst::BufferRef>, length: u32, ) -> Result; fn parent_do_seek(&self, element: &Self::Type, segment: &mut gst::Segment) -> bool; fn parent_query(&self, element: &Self::Type, query: &mut gst::QueryRef) -> bool; fn parent_event(&self, element: &Self::Type, event: &gst::Event) -> bool; fn parent_get_caps( &self, element: &Self::Type, filter: Option<&gst::Caps>, ) -> Option; fn parent_negotiate(&self, element: &Self::Type) -> Result<(), gst::LoggableError>; fn parent_set_caps( &self, element: &Self::Type, caps: &gst::Caps, ) -> Result<(), gst::LoggableError>; fn parent_fixate(&self, element: &Self::Type, caps: gst::Caps) -> gst::Caps; fn parent_unlock(&self, element: &Self::Type) -> Result<(), gst::ErrorMessage>; fn parent_unlock_stop(&self, element: &Self::Type) -> Result<(), gst::ErrorMessage>; } impl BaseSrcImplExt for T { fn parent_start(&self, element: &Self::Type) -> Result<(), gst::ErrorMessage> { unsafe { let data = T::type_data(); let parent_class = data.as_ref().get_parent_class() as *mut ffi::GstBaseSrcClass; (*parent_class) .start .map(|f| { if from_glib(f(element.unsafe_cast_ref::().to_glib_none().0)) { Ok(()) } else { Err(gst::gst_error_msg!( gst::CoreError::StateChange, ["Parent function `start` failed"] )) } }) .unwrap_or(Ok(())) } } fn parent_stop(&self, element: &Self::Type) -> Result<(), gst::ErrorMessage> { unsafe { let data = T::type_data(); let parent_class = data.as_ref().get_parent_class() as *mut ffi::GstBaseSrcClass; (*parent_class) .stop .map(|f| { if from_glib(f(element.unsafe_cast_ref::().to_glib_none().0)) { Ok(()) } else { Err(gst::gst_error_msg!( gst::CoreError::StateChange, ["Parent function `stop` failed"] )) } }) .unwrap_or(Ok(())) } } fn parent_is_seekable(&self, element: &Self::Type) -> bool { unsafe { let data = T::type_data(); let parent_class = data.as_ref().get_parent_class() as *mut ffi::GstBaseSrcClass; (*parent_class) .is_seekable .map(|f| from_glib(f(element.unsafe_cast_ref::().to_glib_none().0))) .unwrap_or(false) } } fn parent_get_size(&self, element: &Self::Type) -> Option { unsafe { let data = T::type_data(); let parent_class = data.as_ref().get_parent_class() as *mut ffi::GstBaseSrcClass; (*parent_class) .get_size .map(|f| { let mut size = mem::MaybeUninit::uninit(); if from_glib(f( element.unsafe_cast_ref::().to_glib_none().0, size.as_mut_ptr(), )) { Some(size.assume_init()) } else { None } }) .unwrap_or(None) } } fn parent_get_times( &self, element: &Self::Type, buffer: &gst::BufferRef, ) -> (gst::ClockTime, gst::ClockTime) { unsafe { let data = T::type_data(); let parent_class = data.as_ref().get_parent_class() as *mut ffi::GstBaseSrcClass; (*parent_class) .get_times .map(|f| { let mut start = mem::MaybeUninit::uninit(); let mut stop = mem::MaybeUninit::uninit(); f( element.unsafe_cast_ref::().to_glib_none().0, buffer.as_mut_ptr(), start.as_mut_ptr(), stop.as_mut_ptr(), ); ( from_glib(start.assume_init()), from_glib(stop.assume_init()), ) }) .unwrap_or((gst::CLOCK_TIME_NONE, gst::CLOCK_TIME_NONE)) } } fn parent_fill( &self, element: &Self::Type, offset: u64, length: u32, buffer: &mut gst::BufferRef, ) -> Result { unsafe { let data = T::type_data(); let parent_class = data.as_ref().get_parent_class() as *mut ffi::GstBaseSrcClass; (*parent_class) .fill .map(|f| { gst::FlowReturn::from_glib(f( element.unsafe_cast_ref::().to_glib_none().0, offset, length, buffer.as_mut_ptr(), )) }) .unwrap_or(gst::FlowReturn::NotSupported) .into_result() } } fn parent_alloc( &self, element: &Self::Type, offset: u64, length: u32, ) -> Result { unsafe { let data = T::type_data(); let parent_class = data.as_ref().get_parent_class() as *mut ffi::GstBaseSrcClass; (*parent_class) .alloc .map(|f| { let mut buffer_ptr: *mut gst::ffi::GstBuffer = ptr::null_mut(); // FIXME: Wrong signature in -sys bindings // https://gitlab.freedesktop.org/gstreamer/gstreamer-rs-sys/issues/3 let buffer_ref = &mut buffer_ptr as *mut _ as *mut gst::ffi::GstBuffer; let res = gst::FlowReturn::from_glib(f( element.unsafe_cast_ref::().to_glib_none().0, offset, length, buffer_ref, )); res.into_result_value(|| from_glib_full(buffer_ref)) }) .unwrap_or(Err(gst::FlowError::NotSupported)) } } fn parent_create( &self, element: &Self::Type, offset: u64, mut buffer: Option<&mut gst::BufferRef>, length: u32, ) -> Result { unsafe { let data = T::type_data(); let parent_class = data.as_ref().get_parent_class() as *mut ffi::GstBaseSrcClass; (*parent_class) .create .map(|f| { let orig_buffer_ptr = buffer .as_mut() .map(|b| b.as_mut_ptr()) .unwrap_or(ptr::null_mut()); let mut buffer_ptr = orig_buffer_ptr; // FIXME: Wrong signature in -sys bindings // https://gitlab.freedesktop.org/gstreamer/gstreamer-rs-sys/issues/3 let buffer_ref = &mut buffer_ptr as *mut _ as *mut gst::ffi::GstBuffer; gst::FlowReturn::from_glib( f( element.unsafe_cast_ref::().to_glib_none().0, offset, length, buffer_ref, ) ).into_result()?; if let Some(passed_buffer) = buffer { if buffer_ptr != orig_buffer_ptr { let new_buffer = gst::BufferRef::from_ptr(buffer_ptr); gst::gst_debug!( gst::CAT_PERFORMANCE, obj: element.unsafe_cast_ref::(), "Returned new buffer from parent create function, copying into passed buffer" ); let mut map = match passed_buffer.map_writable() { Ok(map) => map, Err(_) => { gst::gst_error!( gst::CAT_RUST, obj: element.unsafe_cast_ref::(), "Failed to map passed buffer writable" ); return Err(gst::FlowError::Error); } }; let copied_size = new_buffer.copy_to_slice(0, &mut *map); drop(map); if let Err(copied_size) = copied_size { passed_buffer.set_size(copied_size); } match new_buffer.copy_into(passed_buffer, gst::BUFFER_COPY_METADATA, 0, None) { Ok(_) => Ok(CreateSuccess::FilledBuffer), Err(_) => { gst::gst_error!( gst::CAT_RUST, obj: element.unsafe_cast_ref::(), "Failed to copy buffer metadata" ); Err(gst::FlowError::Error) } } } else { Ok(CreateSuccess::FilledBuffer) } } else { Ok(CreateSuccess::NewBuffer(from_glib_full(buffer_ptr))) } }) .unwrap_or(Err(gst::FlowError::NotSupported)) } } fn parent_do_seek(&self, element: &Self::Type, segment: &mut gst::Segment) -> bool { unsafe { let data = T::type_data(); let parent_class = data.as_ref().get_parent_class() as *mut ffi::GstBaseSrcClass; (*parent_class) .do_seek .map(|f| { from_glib(f( element.unsafe_cast_ref::().to_glib_none().0, segment.to_glib_none_mut().0, )) }) .unwrap_or(false) } } fn parent_query(&self, element: &Self::Type, query: &mut gst::QueryRef) -> bool { unsafe { let data = T::type_data(); let parent_class = data.as_ref().get_parent_class() as *mut ffi::GstBaseSrcClass; (*parent_class) .query .map(|f| { from_glib(f( element.unsafe_cast_ref::().to_glib_none().0, query.as_mut_ptr(), )) }) .unwrap_or(false) } } fn parent_event(&self, element: &Self::Type, event: &gst::Event) -> bool { unsafe { let data = T::type_data(); let parent_class = data.as_ref().get_parent_class() as *mut ffi::GstBaseSrcClass; (*parent_class) .event .map(|f| { from_glib(f( element.unsafe_cast_ref::().to_glib_none().0, event.to_glib_none().0, )) }) .unwrap_or(false) } } fn parent_get_caps( &self, element: &Self::Type, filter: Option<&gst::Caps>, ) -> Option { unsafe { let data = T::type_data(); let parent_class = data.as_ref().get_parent_class() as *mut ffi::GstBaseSrcClass; (*parent_class) .get_caps .map(|f| { from_glib_full(f( element.unsafe_cast_ref::().to_glib_none().0, filter.to_glib_none().0, )) }) .unwrap_or(None) } } fn parent_negotiate(&self, element: &Self::Type) -> Result<(), gst::LoggableError> { unsafe { let data = T::type_data(); let parent_class = data.as_ref().get_parent_class() as *mut ffi::GstBaseSrcClass; (*parent_class) .negotiate .map(|f| { gst::gst_result_from_gboolean!( f(element.unsafe_cast_ref::().to_glib_none().0), gst::CAT_RUST, "Parent function `negotiate` failed" ) }) .unwrap_or(Ok(())) } } fn parent_set_caps( &self, element: &Self::Type, caps: &gst::Caps, ) -> Result<(), gst::LoggableError> { unsafe { let data = T::type_data(); let parent_class = data.as_ref().get_parent_class() as *mut ffi::GstBaseSrcClass; (*parent_class) .set_caps .map(|f| { gst::gst_result_from_gboolean!( f( element.unsafe_cast_ref::().to_glib_none().0, caps.to_glib_none().0 ), gst::CAT_RUST, "Parent function `set_caps` failed" ) }) .unwrap_or(Ok(())) } } fn parent_fixate(&self, element: &Self::Type, caps: gst::Caps) -> gst::Caps { unsafe { let data = T::type_data(); let parent_class = data.as_ref().get_parent_class() as *mut ffi::GstBaseSrcClass; match (*parent_class).fixate { Some(fixate) => from_glib_full(fixate( element.unsafe_cast_ref::().to_glib_none().0, caps.into_ptr(), )), None => caps, } } } fn parent_unlock(&self, element: &Self::Type) -> Result<(), gst::ErrorMessage> { unsafe { let data = T::type_data(); let parent_class = data.as_ref().get_parent_class() as *mut ffi::GstBaseSrcClass; (*parent_class) .unlock .map(|f| { if from_glib(f(element.unsafe_cast_ref::().to_glib_none().0)) { Ok(()) } else { Err(gst::gst_error_msg!( gst::CoreError::Failed, ["Parent function `unlock` failed"] )) } }) .unwrap_or(Ok(())) } } fn parent_unlock_stop(&self, element: &Self::Type) -> Result<(), gst::ErrorMessage> { unsafe { let data = T::type_data(); let parent_class = data.as_ref().get_parent_class() as *mut ffi::GstBaseSrcClass; (*parent_class) .unlock_stop .map(|f| { if from_glib(f(element.unsafe_cast_ref::().to_glib_none().0)) { Ok(()) } else { Err(gst::gst_error_msg!( gst::CoreError::Failed, ["Parent function `unlock_stop` failed"] )) } }) .unwrap_or(Ok(())) } } } unsafe impl IsSubclassable for BaseSrc where ::Instance: PanicPoison, { fn override_vfuncs(klass: &mut glib::Class) { >::override_vfuncs(klass); let klass = klass.as_mut(); klass.start = Some(base_src_start::); klass.stop = Some(base_src_stop::); klass.is_seekable = Some(base_src_is_seekable::); klass.get_size = Some(base_src_get_size::); klass.get_times = Some(base_src_get_times::); klass.fill = Some(base_src_fill::); klass.alloc = Some(base_src_alloc::); klass.create = Some(base_src_create::); klass.do_seek = Some(base_src_do_seek::); klass.query = Some(base_src_query::); klass.event = Some(base_src_event::); klass.get_caps = Some(base_src_get_caps::); klass.negotiate = Some(base_src_negotiate::); klass.set_caps = Some(base_src_set_caps::); klass.fixate = Some(base_src_fixate::); klass.unlock = Some(base_src_unlock::); klass.unlock_stop = Some(base_src_unlock_stop::); } } unsafe extern "C" fn base_src_start( ptr: *mut ffi::GstBaseSrc, ) -> glib::ffi::gboolean where T::Instance: PanicPoison, { let instance = &*(ptr as *mut T::Instance); let imp = instance.get_impl(); let wrap: Borrowed = from_glib_borrow(ptr); gst::gst_panic_to_error!(&wrap, &instance.panicked(), false, { match imp.start(wrap.unsafe_cast_ref()) { Ok(()) => true, Err(err) => { wrap.post_error_message(err); false } } }) .to_glib() } unsafe extern "C" fn base_src_stop(ptr: *mut ffi::GstBaseSrc) -> glib::ffi::gboolean where T::Instance: PanicPoison, { let instance = &*(ptr as *mut T::Instance); let imp = instance.get_impl(); let wrap: Borrowed = from_glib_borrow(ptr); gst::gst_panic_to_error!(&wrap, &instance.panicked(), false, { match imp.stop(wrap.unsafe_cast_ref()) { Ok(()) => true, Err(err) => { wrap.post_error_message(err); false } } }) .to_glib() } unsafe extern "C" fn base_src_is_seekable( ptr: *mut ffi::GstBaseSrc, ) -> glib::ffi::gboolean where T::Instance: PanicPoison, { let instance = &*(ptr as *mut T::Instance); let imp = instance.get_impl(); let wrap: Borrowed = from_glib_borrow(ptr); gst::gst_panic_to_error!(&wrap, &instance.panicked(), false, { imp.is_seekable(wrap.unsafe_cast_ref()) }) .to_glib() } unsafe extern "C" fn base_src_get_size( ptr: *mut ffi::GstBaseSrc, size: *mut u64, ) -> glib::ffi::gboolean where T::Instance: PanicPoison, { let instance = &*(ptr as *mut T::Instance); let imp = instance.get_impl(); let wrap: Borrowed = from_glib_borrow(ptr); gst::gst_panic_to_error!(&wrap, &instance.panicked(), false, { match imp.get_size(wrap.unsafe_cast_ref()) { Some(s) => { *size = s; true } None => false, } }) .to_glib() } unsafe extern "C" fn base_src_get_times( ptr: *mut ffi::GstBaseSrc, buffer: *mut gst::ffi::GstBuffer, start: *mut gst::ffi::GstClockTime, stop: *mut gst::ffi::GstClockTime, ) where T::Instance: PanicPoison, { let instance = &*(ptr as *mut T::Instance); let imp = instance.get_impl(); let wrap: Borrowed = from_glib_borrow(ptr); let buffer = gst::BufferRef::from_ptr(buffer); *start = gst::ffi::GST_CLOCK_TIME_NONE; *stop = gst::ffi::GST_CLOCK_TIME_NONE; gst::gst_panic_to_error!(&wrap, &instance.panicked(), (), { let (start_, stop_) = imp.get_times(wrap.unsafe_cast_ref(), buffer); *start = start_.to_glib(); *stop = stop_.to_glib(); }); } unsafe extern "C" fn base_src_fill( ptr: *mut ffi::GstBaseSrc, offset: u64, length: u32, buffer: *mut gst::ffi::GstBuffer, ) -> gst::ffi::GstFlowReturn where T::Instance: PanicPoison, { let instance = &*(ptr as *mut T::Instance); let imp = instance.get_impl(); let wrap: Borrowed = from_glib_borrow(ptr); let buffer = gst::BufferRef::from_mut_ptr(buffer); gst::gst_panic_to_error!(&wrap, &instance.panicked(), gst::FlowReturn::Error, { imp.fill(wrap.unsafe_cast_ref(), offset, length, buffer) .into() }) .to_glib() } unsafe extern "C" fn base_src_alloc( ptr: *mut ffi::GstBaseSrc, offset: u64, length: u32, buffer_ptr: *mut gst::ffi::GstBuffer, ) -> gst::ffi::GstFlowReturn where T::Instance: PanicPoison, { let instance = &*(ptr as *mut T::Instance); let imp = instance.get_impl(); let wrap: Borrowed = from_glib_borrow(ptr); // FIXME: Wrong signature in -sys bindings // https://gitlab.freedesktop.org/gstreamer/gstreamer-rs-sys/issues/3 let buffer_ptr = buffer_ptr as *mut *mut gst::ffi::GstBuffer; gst::gst_panic_to_error!(&wrap, &instance.panicked(), gst::FlowReturn::Error, { match imp.alloc(wrap.unsafe_cast_ref(), offset, length) { Ok(buffer) => { *buffer_ptr = buffer.into_ptr(); gst::FlowReturn::Ok } Err(err) => gst::FlowReturn::from(err), } }) .to_glib() } unsafe extern "C" fn base_src_create( ptr: *mut ffi::GstBaseSrc, offset: u64, length: u32, buffer_ptr: *mut gst::ffi::GstBuffer, ) -> gst::ffi::GstFlowReturn where T::Instance: PanicPoison, { let instance = &*(ptr as *mut T::Instance); let imp = instance.get_impl(); let wrap: Borrowed = from_glib_borrow(ptr); // FIXME: Wrong signature in -sys bindings // https://gitlab.freedesktop.org/gstreamer/gstreamer-rs-sys/issues/3 let buffer_ptr = buffer_ptr as *mut *mut gst::ffi::GstBuffer; let mut buffer = if (*buffer_ptr).is_null() { None } else { Some(gst::BufferRef::from_mut_ptr(*buffer_ptr)) }; gst::gst_panic_to_error!(&wrap, &instance.panicked(), gst::FlowReturn::Error, { match imp.create( wrap.unsafe_cast_ref(), offset, buffer.as_deref_mut(), length, ) { Ok(CreateSuccess::NewBuffer(new_buffer)) => { if let Some(passed_buffer) = buffer { if passed_buffer.as_ptr() != new_buffer.as_ptr() { gst::gst_debug!( gst::CAT_PERFORMANCE, obj: &*wrap, "Returned new buffer from create function, copying into passed buffer" ); let mut map = match passed_buffer.map_writable() { Ok(map) => map, Err(_) => { gst::gst_error!( gst::CAT_RUST, obj: &*wrap, "Failed to map passed buffer writable" ); return gst::FlowReturn::Error; } }; let copied_size = new_buffer.copy_to_slice(0, &mut *map); drop(map); if let Err(copied_size) = copied_size { passed_buffer.set_size(copied_size); } match new_buffer.copy_into( passed_buffer, gst::BUFFER_COPY_METADATA, 0, None, ) { Ok(_) => gst::FlowReturn::Ok, Err(_) => { gst::gst_error!( gst::CAT_RUST, obj: &*wrap, "Failed to copy buffer metadata" ); gst::FlowReturn::Error } } } else { gst::FlowReturn::Ok } } else { *buffer_ptr = new_buffer.into_ptr(); gst::FlowReturn::Ok } } Ok(CreateSuccess::FilledBuffer) => gst::FlowReturn::Ok, Err(err) => gst::FlowReturn::from(err), } }) .to_glib() } unsafe extern "C" fn base_src_do_seek( ptr: *mut ffi::GstBaseSrc, segment: *mut gst::ffi::GstSegment, ) -> glib::ffi::gboolean where T::Instance: PanicPoison, { let instance = &*(ptr as *mut T::Instance); let imp = instance.get_impl(); let wrap: Borrowed = from_glib_borrow(ptr); gst::gst_panic_to_error!(&wrap, &instance.panicked(), false, { let mut s = from_glib_none(segment); let res = imp.do_seek(wrap.unsafe_cast_ref(), &mut s); ptr::write(segment, *(s.to_glib_none().0)); res }) .to_glib() } unsafe extern "C" fn base_src_query( ptr: *mut ffi::GstBaseSrc, query_ptr: *mut gst::ffi::GstQuery, ) -> glib::ffi::gboolean where T::Instance: PanicPoison, { let instance = &*(ptr as *mut T::Instance); let imp = instance.get_impl(); let wrap: Borrowed = from_glib_borrow(ptr); let query = gst::QueryRef::from_mut_ptr(query_ptr); gst::gst_panic_to_error!(&wrap, &instance.panicked(), false, { BaseSrcImpl::query(imp, wrap.unsafe_cast_ref(), query) }) .to_glib() } unsafe extern "C" fn base_src_event( ptr: *mut ffi::GstBaseSrc, event_ptr: *mut gst::ffi::GstEvent, ) -> glib::ffi::gboolean where T::Instance: PanicPoison, { let instance = &*(ptr as *mut T::Instance); let imp = instance.get_impl(); let wrap: Borrowed = from_glib_borrow(ptr); gst::gst_panic_to_error!(&wrap, &instance.panicked(), false, { imp.event(wrap.unsafe_cast_ref(), &from_glib_borrow(event_ptr)) }) .to_glib() } unsafe extern "C" fn base_src_get_caps( ptr: *mut ffi::GstBaseSrc, filter: *mut gst::ffi::GstCaps, ) -> *mut gst::ffi::GstCaps where T::Instance: PanicPoison, { let instance = &*(ptr as *mut T::Instance); let imp = instance.get_impl(); let wrap: Borrowed = from_glib_borrow(ptr); let filter = Option::::from_glib_borrow(filter); gst::gst_panic_to_error!(&wrap, &instance.panicked(), None, { imp.get_caps(wrap.unsafe_cast_ref(), filter.as_ref().as_ref()) }) .map(|caps| caps.into_ptr()) .unwrap_or(ptr::null_mut()) } unsafe extern "C" fn base_src_negotiate( ptr: *mut ffi::GstBaseSrc, ) -> glib::ffi::gboolean where T::Instance: PanicPoison, { let instance = &*(ptr as *mut T::Instance); let imp = instance.get_impl(); let wrap: Borrowed = from_glib_borrow(ptr); gst::gst_panic_to_error!(&wrap, &instance.panicked(), false, { match imp.negotiate(wrap.unsafe_cast_ref()) { Ok(()) => true, Err(err) => { err.log_with_object(&*wrap); false } } }) .to_glib() } unsafe extern "C" fn base_src_set_caps( ptr: *mut ffi::GstBaseSrc, caps: *mut gst::ffi::GstCaps, ) -> glib::ffi::gboolean where T::Instance: PanicPoison, { let instance = &*(ptr as *mut T::Instance); let imp = instance.get_impl(); let wrap: Borrowed = from_glib_borrow(ptr); let caps = from_glib_borrow(caps); gst::gst_panic_to_error!(&wrap, &instance.panicked(), false, { match imp.set_caps(wrap.unsafe_cast_ref(), &caps) { Ok(()) => true, Err(err) => { err.log_with_object(&*wrap); false } } }) .to_glib() } unsafe extern "C" fn base_src_fixate( ptr: *mut ffi::GstBaseSrc, caps: *mut gst::ffi::GstCaps, ) -> *mut gst::ffi::GstCaps where T::Instance: PanicPoison, { let instance = &*(ptr as *mut T::Instance); let imp = instance.get_impl(); let wrap: Borrowed = from_glib_borrow(ptr); let caps = from_glib_full(caps); gst::gst_panic_to_error!(&wrap, &instance.panicked(), gst::Caps::new_empty(), { imp.fixate(wrap.unsafe_cast_ref(), caps) }) .into_ptr() } unsafe extern "C" fn base_src_unlock( ptr: *mut ffi::GstBaseSrc, ) -> glib::ffi::gboolean where T::Instance: PanicPoison, { let instance = &*(ptr as *mut T::Instance); let imp = instance.get_impl(); let wrap: Borrowed = from_glib_borrow(ptr); gst::gst_panic_to_error!(&wrap, &instance.panicked(), false, { match imp.unlock(wrap.unsafe_cast_ref()) { Ok(()) => true, Err(err) => { wrap.post_error_message(err); false } } }) .to_glib() } unsafe extern "C" fn base_src_unlock_stop( ptr: *mut ffi::GstBaseSrc, ) -> glib::ffi::gboolean where T::Instance: PanicPoison, { let instance = &*(ptr as *mut T::Instance); let imp = instance.get_impl(); let wrap: Borrowed = from_glib_borrow(ptr); gst::gst_panic_to_error!(&wrap, &instance.panicked(), false, { match imp.unlock_stop(wrap.unsafe_cast_ref()) { Ok(()) => true, Err(err) => { wrap.post_error_message(err); false } } }) .to_glib() }