gstreamer/
object.rs
1use glib::{prelude::*, signal::SignalHandlerId, translate::*};
4
5use crate::{ffi, ClockTime, Object, ObjectFlags};
6
7mod sealed {
8 pub trait Sealed {}
9 impl<T: super::IsA<super::Object>> Sealed for T {}
10}
11
12pub trait GstObjectExtManual: sealed::Sealed + IsA<Object> + 'static {
13 #[doc(alias = "deep-notify")]
14 fn connect_deep_notify<
15 F: Fn(&Self, &crate::Object, &glib::ParamSpec) + Send + Sync + 'static,
16 >(
17 &self,
18 name: Option<&str>,
19 f: F,
20 ) -> SignalHandlerId {
21 let signal_name = if let Some(name) = name {
22 format!("deep-notify::{name}")
23 } else {
24 "deep-notify".into()
25 };
26
27 let obj: Borrowed<glib::Object> =
28 unsafe { from_glib_borrow(self.as_ptr() as *mut glib::gobject_ffi::GObject) };
29
30 obj.connect(signal_name.as_str(), false, move |values| {
31 let obj: Self = unsafe {
35 values[0]
36 .get::<crate::Object>()
37 .unwrap_or_else(|err| panic!("Object signal \"deep-notify\": values[0]: {err}"))
38 .unsafe_cast()
39 };
40 let prop_obj: crate::Object = values[1]
41 .get()
42 .unwrap_or_else(|err| panic!("Object signal \"deep-notify\": values[1]: {err}"));
43
44 let pspec = unsafe {
45 let pspec = glib::gobject_ffi::g_value_get_param(values[2].to_glib_none().0);
46 from_glib_none(pspec)
47 };
48
49 f(&obj, &prop_obj, &pspec);
50
51 None
52 })
53 }
54
55 fn set_object_flags(&self, flags: ObjectFlags) {
56 unsafe {
57 let ptr: *mut ffi::GstObject = self.as_ptr() as *mut _;
58 let _guard = self.as_ref().object_lock();
59 (*ptr).flags |= flags.into_glib();
60 }
61 }
62
63 fn unset_object_flags(&self, flags: ObjectFlags) {
64 unsafe {
65 let ptr: *mut ffi::GstObject = self.as_ptr() as *mut _;
66 let _guard = self.as_ref().object_lock();
67 (*ptr).flags &= !flags.into_glib();
68 }
69 }
70
71 #[doc(alias = "get_object_flags")]
72 fn object_flags(&self) -> ObjectFlags {
73 unsafe {
74 let ptr: *mut ffi::GstObject = self.as_ptr() as *mut _;
75 let _guard = self.as_ref().object_lock();
76 from_glib((*ptr).flags)
77 }
78 }
79
80 #[doc(alias = "get_g_value_array")]
81 #[doc(alias = "gst_object_get_g_value_array")]
82 fn g_value_array(
83 &self,
84 property_name: &str,
85 timestamp: ClockTime,
86 interval: ClockTime,
87 values: &mut [glib::Value],
88 ) -> Result<(), glib::error::BoolError> {
89 let n_values = values.len() as u32;
90 unsafe {
91 glib::result_from_gboolean!(
92 ffi::gst_object_get_g_value_array(
93 self.as_ref().to_glib_none().0,
94 property_name.to_glib_none().0,
95 timestamp.into_glib(),
96 interval.into_glib(),
97 n_values,
98 values.as_mut_ptr() as *mut glib::gobject_ffi::GValue,
99 ),
100 "Failed to get value array"
101 )
102 }
103 }
104
105 #[inline]
106 fn object_lock(&self) -> crate::utils::ObjectLockGuard<Self> {
107 crate::utils::ObjectLockGuard::acquire(self)
108 }
109}
110
111impl<O: IsA<Object>> GstObjectExtManual for O {}
112
113#[cfg(test)]
114mod tests {
115 use std::sync::{Arc, Mutex};
116
117 use super::*;
118 use crate::prelude::*;
119
120 #[test]
121 fn test_deep_notify() {
122 crate::init().unwrap();
123
124 let bin = crate::Bin::new();
125 let identity = crate::ElementFactory::make("identity")
126 .name("id")
127 .build()
128 .unwrap();
129 bin.add(&identity).unwrap();
130
131 let notify = Arc::new(Mutex::new(None));
132 let notify_clone = notify.clone();
133 bin.connect_deep_notify(None, move |_, id, prop| {
134 *notify_clone.lock().unwrap() = Some((id.clone(), prop.name()));
135 });
136
137 identity.set_property("silent", false);
138 assert_eq!(
139 *notify.lock().unwrap(),
140 Some((identity.upcast::<crate::Object>(), "silent"))
141 );
142 }
143}