// Take a look at the license at the top of the repository in the LICENSE file. use std::mem::transmute; use glib::{prelude::*, subclass::prelude::*, translate::*}; use crate::RTSPMediaFactory; pub trait RTSPMediaFactoryImpl: RTSPMediaFactoryImplExt + ObjectImpl + Send + Sync { fn gen_key(&self, url: &gst_rtsp::RTSPUrl) -> Option { self.parent_gen_key(url) } fn create_element(&self, url: &gst_rtsp::RTSPUrl) -> Option { self.parent_create_element(url) } fn construct(&self, url: &gst_rtsp::RTSPUrl) -> Option { self.parent_construct(url) } fn create_pipeline(&self, media: &crate::RTSPMedia) -> Option { self.parent_create_pipeline(media) } fn configure(&self, media: &crate::RTSPMedia) { self.parent_configure(media) } fn media_constructed(&self, media: &crate::RTSPMedia) { self.parent_media_constructed(media) } fn media_configure(&self, media: &crate::RTSPMedia) { self.parent_media_configure(media) } } mod sealed { pub trait Sealed {} impl Sealed for T {} } pub trait RTSPMediaFactoryImplExt: sealed::Sealed + ObjectSubclass { fn parent_gen_key(&self, url: &gst_rtsp::RTSPUrl) -> Option { unsafe { let data = Self::type_data(); let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTSPMediaFactoryClass; (*parent_class) .gen_key .map(|f| { from_glib_full(f( self.obj() .unsafe_cast_ref::() .to_glib_none() .0, url.to_glib_none().0, )) }) .unwrap_or(None) } } fn parent_create_element(&self, url: &gst_rtsp::RTSPUrl) -> Option { unsafe { let data = Self::type_data(); let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTSPMediaFactoryClass; (*parent_class) .create_element .map(|f| { from_glib_none(f( self.obj() .unsafe_cast_ref::() .to_glib_none() .0, url.to_glib_none().0, )) }) .unwrap_or(None) } } fn parent_construct(&self, url: &gst_rtsp::RTSPUrl) -> Option { unsafe { let data = Self::type_data(); let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTSPMediaFactoryClass; (*parent_class) .construct .map(|f| { from_glib_full(f( self.obj() .unsafe_cast_ref::() .to_glib_none() .0, url.to_glib_none().0, )) }) .unwrap_or(None) } } fn parent_create_pipeline(&self, media: &crate::RTSPMedia) -> Option { unsafe { let data = Self::type_data(); let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTSPMediaFactoryClass; (*parent_class) .create_pipeline .map(|f| { let ptr = f( self.obj() .unsafe_cast_ref::() .to_glib_none() .0, media.to_glib_none().0, ) as *mut gst::ffi::GstPipeline; // See https://gitlab.freedesktop.org/gstreamer/gst-rtsp-server/merge_requests/109 if glib::gobject_ffi::g_object_is_floating(ptr as *mut _) != glib::ffi::GFALSE { glib::gobject_ffi::g_object_ref_sink(ptr as *mut _); } from_glib_none(ptr) }) .unwrap_or(None) } } fn parent_configure(&self, media: &crate::RTSPMedia) { unsafe { let data = Self::type_data(); let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTSPMediaFactoryClass; if let Some(f) = (*parent_class).configure { f( self.obj() .unsafe_cast_ref::() .to_glib_none() .0, media.to_glib_none().0, ); } } } fn parent_media_constructed(&self, media: &crate::RTSPMedia) { unsafe { let data = Self::type_data(); let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTSPMediaFactoryClass; if let Some(f) = (*parent_class).media_constructed { f( self.obj() .unsafe_cast_ref::() .to_glib_none() .0, media.to_glib_none().0, ); } } } fn parent_media_configure(&self, media: &crate::RTSPMedia) { unsafe { let data = Self::type_data(); let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTSPMediaFactoryClass; if let Some(f) = (*parent_class).media_configure { f( self.obj() .unsafe_cast_ref::() .to_glib_none() .0, media.to_glib_none().0, ); } } } } impl RTSPMediaFactoryImplExt for T {} unsafe impl IsSubclassable for RTSPMediaFactory { fn class_init(klass: &mut glib::Class) { Self::parent_class_init::(klass); let klass = klass.as_mut(); klass.gen_key = Some(factory_gen_key::); klass.create_element = Some(factory_create_element::); klass.construct = Some(factory_construct::); klass.create_pipeline = Some(factory_create_pipeline::); klass.configure = Some(factory_configure::); klass.media_constructed = Some(factory_media_constructed::); klass.media_configure = Some(factory_media_configure::); } } unsafe extern "C" fn factory_gen_key( ptr: *mut ffi::GstRTSPMediaFactory, url: *const gst_rtsp::ffi::GstRTSPUrl, ) -> *mut std::os::raw::c_char { let instance = &*(ptr as *mut T::Instance); let imp = instance.imp(); imp.gen_key(&from_glib_borrow(url)).into_glib_ptr() } unsafe extern "C" fn factory_create_element( ptr: *mut ffi::GstRTSPMediaFactory, url: *const gst_rtsp::ffi::GstRTSPUrl, ) -> *mut gst::ffi::GstElement { let instance = &*(ptr as *mut T::Instance); let imp = instance.imp(); let element = imp.create_element(&from_glib_borrow(url)).into_glib_ptr(); glib::gobject_ffi::g_object_force_floating(element as *mut _); element } unsafe extern "C" fn factory_construct( ptr: *mut ffi::GstRTSPMediaFactory, url: *const gst_rtsp::ffi::GstRTSPUrl, ) -> *mut ffi::GstRTSPMedia { let instance = &*(ptr as *mut T::Instance); let imp = instance.imp(); imp.construct(&from_glib_borrow(url)).into_glib_ptr() } unsafe extern "C" fn factory_create_pipeline( ptr: *mut ffi::GstRTSPMediaFactory, media: *mut ffi::GstRTSPMedia, ) -> *mut gst::ffi::GstElement { static PIPELINE_QUARK: std::sync::OnceLock = std::sync::OnceLock::new(); let pipeline_quark = PIPELINE_QUARK.get_or_init(|| glib::Quark::from_str("gstreamer-rs-rtsp-media-pipeline")); let instance = &*(ptr as *mut T::Instance); let imp = instance.imp(); let pipeline: *mut gst::ffi::GstPipeline = imp .create_pipeline(&from_glib_borrow(media)) .into_glib_ptr(); // FIXME We somehow need to ensure the pipeline actually stays alive... glib::gobject_ffi::g_object_set_qdata_full( media as *mut _, pipeline_quark.into_glib(), pipeline as *mut _, Some(transmute::<_, unsafe extern "C" fn(glib::ffi::gpointer)>( glib::gobject_ffi::g_object_unref as *const (), )), ); pipeline as *mut _ } unsafe extern "C" fn factory_configure( ptr: *mut ffi::GstRTSPMediaFactory, media: *mut ffi::GstRTSPMedia, ) { let instance = &*(ptr as *mut T::Instance); let imp = instance.imp(); imp.configure(&from_glib_borrow(media)); } unsafe extern "C" fn factory_media_constructed( ptr: *mut ffi::GstRTSPMediaFactory, media: *mut ffi::GstRTSPMedia, ) { let instance = &*(ptr as *mut T::Instance); let imp = instance.imp(); imp.media_constructed(&from_glib_borrow(media)); } unsafe extern "C" fn factory_media_configure( ptr: *mut ffi::GstRTSPMediaFactory, media: *mut ffi::GstRTSPMedia, ) { let instance = &*(ptr as *mut T::Instance); let imp = instance.imp(); imp.media_configure(&from_glib_borrow(media)); }