From ecf9a43692b068da6337154483888e47f06818a9 Mon Sep 17 00:00:00 2001 From: Prakash Duggaraju Date: Sun, 27 Jun 2021 10:26:53 -0700 Subject: [PATCH] rtsp-server: Add support for subclassing GstRtspMountPoints Implement MountPointsImpl and MountPointsExt to allow subclassing. Update the example to show usage. --- examples/src/bin/rtsp-server-subclass.rs | 56 ++++++++++++++ gstreamer-rtsp-server/src/subclass/mod.rs | 2 + .../src/subclass/rtsp_mount_points.rs | 73 +++++++++++++++++++ 3 files changed, 131 insertions(+) create mode 100644 gstreamer-rtsp-server/src/subclass/rtsp_mount_points.rs diff --git a/examples/src/bin/rtsp-server-subclass.rs b/examples/src/bin/rtsp-server-subclass.rs index 35e29f396..e4d96ec68 100644 --- a/examples/src/bin/rtsp-server-subclass.rs +++ b/examples/src/bin/rtsp-server-subclass.rs @@ -26,6 +26,10 @@ struct UsageError(#[error(not(source))] String); fn main_loop() -> Result<(), Error> { let main_loop = glib::MainLoop::new(None, false); let server = server::Server::default(); + + let mounts = mount_points::MountPoints::default(); + server.set_mount_points(Some(&mounts)); + // Much like HTTP servers, RTSP servers have multiple endpoints that // provide different streams. Here, we ask our server to give // us a reference to his list of endpoints, so we can add our @@ -329,6 +333,58 @@ mod client { } } +mod mount_points { + use gst_rtsp_server::subclass::prelude::*; + + mod imp { + use super::*; + + // This is the private data of our mount points + #[derive(Default)] + pub struct MountPoints {} + + // This trait registers our type with the GObject object system and + // provides the entry points for creating a new instance and setting + // up the class data + #[glib::object_subclass] + impl ObjectSubclass for MountPoints { + const NAME: &'static str = "RsRTSPMountPoints"; + type Type = super::MountPoints; + type ParentType = gst_rtsp_server::RTSPMountPoints; + } + + // Implementation of glib::Object virtual methods + impl ObjectImpl for MountPoints {} + + // Implementation of gst_rtsp_server::RTSPClient virtual methods + impl RTSPMountPointsImpl for MountPoints { + fn make_path( + &self, + mount_points: &Self::Type, + url: &gst_rtsp::RTSPUrl, + ) -> Option { + println!("Make path called for {:?} ", url); + self.parent_make_path(mount_points, url) + } + } + } + + glib::wrapper! { + pub struct MountPoints(ObjectSubclass) @extends gst_rtsp_server::RTSPMountPoints; + } + + // MountPoints must be Send+Sync, and ours is + unsafe impl Send for MountPoints {} + unsafe impl Sync for MountPoints {} + + impl Default for MountPoints { + // Creates a new instance of our factory + fn default() -> Self { + glib::Object::new(&[]).expect("Failed to create mount points") + } + } +} + fn example_main() -> Result<(), Error> { gst::init()?; main_loop() diff --git a/gstreamer-rtsp-server/src/subclass/mod.rs b/gstreamer-rtsp-server/src/subclass/mod.rs index da6e098ff..a866e94d2 100644 --- a/gstreamer-rtsp-server/src/subclass/mod.rs +++ b/gstreamer-rtsp-server/src/subclass/mod.rs @@ -5,6 +5,7 @@ mod rtsp_client; mod rtsp_media; mod rtsp_media_factory; +mod rtsp_mount_points; mod rtsp_server; pub use self::rtsp_media::SDPInfo; @@ -16,5 +17,6 @@ pub mod prelude { pub use super::rtsp_client::{RTSPClientImpl, RTSPClientImplExt}; pub use super::rtsp_media::{RTSPMediaImpl, RTSPMediaImplExt}; pub use super::rtsp_media_factory::{RTSPMediaFactoryImpl, RTSPMediaFactoryImplExt}; + pub use super::rtsp_mount_points::{RTSPMountPointsImpl, RTSPMountPointsImplExt}; pub use super::rtsp_server::{RTSPServerImpl, RTSPServerImplExt}; } diff --git a/gstreamer-rtsp-server/src/subclass/rtsp_mount_points.rs b/gstreamer-rtsp-server/src/subclass/rtsp_mount_points.rs new file mode 100644 index 000000000..6ef166096 --- /dev/null +++ b/gstreamer-rtsp-server/src/subclass/rtsp_mount_points.rs @@ -0,0 +1,73 @@ +// 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_rtsp::ffi::GstRTSPUrl; + +use crate::RTSPMountPoints; + +pub trait RTSPMountPointsImpl: RTSPMountPointsImplExt + ObjectImpl + Send + Sync { + fn make_path( + &self, + mount_points: &Self::Type, + url: &gst_rtsp::RTSPUrl, + ) -> Option { + self.parent_make_path(mount_points, url) + } +} + +pub trait RTSPMountPointsImplExt: ObjectSubclass { + fn parent_make_path( + &self, + mount_points: &Self::Type, + url: &gst_rtsp::RTSPUrl, + ) -> Option; +} + +impl RTSPMountPointsImplExt for T { + fn parent_make_path( + &self, + mount_points: &Self::Type, + url: &gst_rtsp::RTSPUrl, + ) -> Option { + unsafe { + let data = Self::type_data(); + let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTSPMountPointsClass; + let f = (*parent_class) + .make_path + .expect("No `make_path` virtual method implementation in parent class"); + from_glib_full(f( + mount_points + .unsafe_cast_ref::() + .to_glib_none() + .0, + url.to_glib_none().0, + )) + } + } +} + +unsafe impl IsSubclassable for RTSPMountPoints { + fn class_init(klass: &mut glib::Class) { + >::class_init(klass); + let klass = klass.as_mut(); + klass.make_path = Some(mount_points_make_path::); + } + + fn instance_init(instance: &mut glib::subclass::InitializingObject) { + >::instance_init(instance); + } +} + +unsafe extern "C" fn mount_points_make_path( + ptr: *mut ffi::GstRTSPMountPoints, + url: *const GstRTSPUrl, +) -> *mut std::os::raw::c_char { + let instance = &*(ptr as *mut T::Instance); + let imp = instance.impl_(); + let wrap: Borrowed = from_glib_borrow(ptr); + + imp.make_path(wrap.unsafe_cast_ref(), &from_glib_borrow(url)) + .to_glib_full() +}