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