1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use glib::{prelude::*, subclass::prelude::*, translate::*};
4
5use super::prelude::*;
6use crate::{
7 ffi, Bin, Buffer, BufferList, Element, Event, FlowError, FlowSuccess, Message, MiniObject,
8 Object, Pad, PadLinkError, PadLinkSuccess, QueryRef, StateChange, StateChangeError,
9 StateChangeSuccess, Tracer,
10};
11
12#[allow(unused_variables)]
13pub trait TracerImpl: TracerImplExt + GstObjectImpl + Send + Sync {
14 fn bin_add_post(&self, ts: u64, bin: &Bin, element: &Element, success: bool) {}
15 fn bin_add_pre(&self, ts: u64, bin: &Bin, element: &Element) {}
16 fn bin_remove_post(&self, ts: u64, bin: &Bin, success: bool) {}
17 fn bin_remove_pre(&self, ts: u64, bin: &Bin, element: &Element) {}
18 fn element_new(&self, ts: u64, element: &Element) {}
19 fn element_add_pad(&self, ts: u64, element: &Element, pad: &Pad) {}
20 fn element_remove_pad(&self, ts: u64, element: &Element, pad: &Pad) {}
21 fn element_change_state_post(
22 &self,
23 ts: u64,
24 element: &Element,
25 change: StateChange,
26 result: Result<StateChangeSuccess, StateChangeError>,
27 ) {
28 }
29 fn element_change_state_pre(&self, ts: u64, element: &Element, change: StateChange) {}
30 fn element_post_message_post(&self, ts: u64, element: &Element, success: bool) {}
31 fn element_post_message_pre(&self, ts: u64, element: &Element, message: &Message) {}
32 fn element_query_post(&self, ts: u64, element: &Element, query: &QueryRef, success: bool) {}
33 fn element_query_pre(&self, ts: u64, element: &Element, query: &QueryRef) {}
34 // rustdoc-stripper-ignore-next
35 /// Hook to be called before the GstMiniObject has been fully initialized.
36 fn mini_object_created(&self, ts: u64, object: std::ptr::NonNull<ffi::GstMiniObject>) {}
37 // rustdoc-stripper-ignore-next
38 /// Hook to be called after the GstMiniObject has been finalized.
39 fn mini_object_destroyed(&self, ts: u64, object: std::ptr::NonNull<ffi::GstMiniObject>) {}
40 fn mini_object_reffed(&self, ts: u64, object: &MiniObject, new_refcount: i32) {}
41 fn mini_object_unreffed(&self, ts: u64, object: &MiniObject, new_refcount: i32) {}
42 fn object_created(&self, ts: u64, object: &Object) {}
43 // rustdoc-stripper-ignore-next
44 /// Hook to be called after the GstObject has been finalized.
45 fn object_destroyed(&self, ts: u64, object: std::ptr::NonNull<ffi::GstObject>) {}
46 fn object_reffed(&self, ts: u64, object: &Object, new_refcount: i32) {}
47 fn object_unreffed(&self, ts: u64, object: &Object, new_refcount: i32) {}
48 fn pad_link_post(
49 &self,
50 ts: u64,
51 src: &Pad,
52 sink: &Pad,
53 result: Result<PadLinkSuccess, PadLinkError>,
54 ) {
55 }
56 fn pad_link_pre(&self, ts: u64, src: &Pad, sink: &Pad) {}
57 fn pad_pull_range_post(&self, ts: u64, pad: &Pad, result: Result<&Buffer, FlowError>) {}
58 fn pad_pull_range_pre(&self, ts: u64, pad: &Pad, offset: u64, size: u32) {}
59 fn pad_push_event_post(&self, ts: u64, pad: &Pad, success: bool) {}
60 fn pad_push_event_pre(&self, ts: u64, pad: &Pad, event: &Event) {}
61 #[cfg(feature = "v1_22")]
62 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
63 fn pad_chain_list_post(&self, ts: u64, pad: &Pad, result: Result<FlowSuccess, FlowError>) {}
64 #[cfg(feature = "v1_22")]
65 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
66 fn pad_chain_list_pre(&self, ts: u64, pad: &Pad, buffer_list: &BufferList) {}
67 #[cfg(feature = "v1_22")]
68 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
69 fn pad_chain_post(&self, ts: u64, pad: &Pad, result: Result<FlowSuccess, FlowError>) {}
70 #[cfg(feature = "v1_22")]
71 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
72 fn pad_chain_pre(&self, ts: u64, pad: &Pad, buffer: &Buffer) {}
73 fn pad_push_list_post(&self, ts: u64, pad: &Pad, result: Result<FlowSuccess, FlowError>) {}
74 fn pad_push_list_pre(&self, ts: u64, pad: &Pad, buffer_list: &BufferList) {}
75 fn pad_push_post(&self, ts: u64, pad: &Pad, result: Result<FlowSuccess, FlowError>) {}
76 fn pad_push_pre(&self, ts: u64, pad: &Pad, buffer: &Buffer) {}
77 fn pad_query_post(&self, ts: u64, pad: &Pad, query: &QueryRef, success: bool) {}
78 fn pad_query_pre(&self, ts: u64, pad: &Pad, query: &QueryRef) {}
79 fn pad_unlink_post(&self, ts: u64, src: &Pad, sink: &Pad, success: bool) {}
80 fn pad_unlink_pre(&self, ts: u64, src: &Pad, sink: &Pad) {}
81 #[cfg(feature = "v1_20")]
82 #[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
83 fn plugin_feature_loaded(&self, ts: u64, feature: &crate::PluginFeature) {}
84}
85
86unsafe impl<T: TracerImpl> IsSubclassable<T> for Tracer {}
87
88pub trait TracerImplExt: ObjectSubclass {
89 // rustdoc-stripper-ignore-next
90 /// Register a corresponding hook to be called for this tracer when certain events occur.
91 ///
92 /// Upon an event a corresponding method in `TracerImpl` will be called.
93 fn register_hook(&self, hook: TracerHook);
94}
95
96macro_rules! define_tracer_hooks {
97 ($($(#[$attr:meta])* $name: ident($quark: literal) = |$this: ident, $ts: ident, $($cb_arg: ident: $cb_arg_ty: ty),*| $impl: block;)*) => {
98 pub enum TracerHook {
99 $($(#[$attr])* $name),*
100 }
101 impl<T: TracerImpl> TracerImplExt for T {
102 fn register_hook(&self, hook: TracerHook) {
103 use TracerHook::*;
104 let (hook_type, callback) = match hook {
105 $($(#[$attr])* $name => {
106 #[allow(non_snake_case)]
107 unsafe extern "C" fn callback<T: TracerImpl>(
108 $this: *mut ffi::GstTracer,
109 $ts: u64,
110 $($cb_arg: $cb_arg_ty),*
111 ) {
112 let $this = Tracer::from_glib_borrow($this);
113 let $this = T::from_obj($this.unsafe_cast_ref());
114 $impl
115 }
116 (
117 concat!($quark, "\0"),
118 callback::<T> as unsafe extern "C" fn(_, _, $($cb_arg_ty),*) as *const ()
119 )
120 },)*
121 };
122 unsafe {
123 let instance = self.obj();
124 ffi::gst_tracing_register_hook(
125 instance.to_glib_none().0 as *mut ffi::GstTracer,
126 hook_type.as_ptr() as *const _,
127 Some(std::mem::transmute::<_, extern "C" fn()>(callback)),
128 );
129 }
130 }
131 }
132 };
133}
134
135define_tracer_hooks! {
136 BinAddPost("bin-add-post") = |this, ts, b: *mut ffi::GstBin, e: *mut ffi::GstElement, r: glib::ffi::gboolean| {
137 let b = Bin::from_glib_borrow(b);
138 let e = Element::from_glib_borrow(e);
139 this.bin_add_post(ts, &b, &e, bool::from_glib(r))
140 };
141 BinAddPre("bin-add-pre") = |this, ts, b: *mut ffi::GstBin, e: *mut ffi::GstElement| {
142 let b = Bin::from_glib_borrow(b);
143 let e = Element::from_glib_borrow(e);
144 this.bin_add_pre(ts, &b, &e)
145 };
146 BinRemovePost("bin-remove-post") = |this, ts, b: *mut ffi::GstBin, r: glib::ffi::gboolean| {
147 let b = Bin::from_glib_borrow(b);
148 this.bin_remove_post(ts, &b, bool::from_glib(r))
149 };
150 BinRemovePre("bin-remove-pre") = |this, ts, b: *mut ffi::GstBin, e: *mut ffi::GstElement| {
151 let b = Bin::from_glib_borrow(b);
152 let e = Element::from_glib_borrow(e);
153 this.bin_remove_pre(ts, &b, &e)
154 };
155 ElementNew("element-new") = |this, ts, e: *mut ffi::GstElement| {
156 let e = Element::from_glib_borrow(e);
157 this.element_new(ts, &e)
158 };
159 ElementAddPad("element-add-pad") = |this, ts, e: *mut ffi::GstElement, p: *mut ffi::GstPad| {
160 let e = Element::from_glib_borrow(e);
161 let p = Pad::from_glib_borrow(p);
162 this.element_add_pad(ts, &e, &p)
163 };
164 ElementRemovePad("element-remove-pad") = |this, ts, e: *mut ffi::GstElement, p: *mut ffi::GstPad| {
165 let e = Element::from_glib_borrow(e);
166 let p = Pad::from_glib_borrow(p);
167 this.element_remove_pad(ts, &e, &p)
168 };
169 ElementChangeStatePost("element-change-state-post") = |this, ts, e: *mut ffi::GstElement, c: ffi::GstStateChange, r: ffi::GstStateChangeReturn| {
170 let e = Element::from_glib_borrow(e);
171 this.element_change_state_post(ts, &e, StateChange::from_glib(c), try_from_glib(r))
172 };
173 ElementChangeStatePre("element-change-state-pre") = |this, ts, e: *mut ffi::GstElement, c: ffi::GstStateChange| {
174 let e = Element::from_glib_borrow(e);
175 this.element_change_state_pre(ts, &e, StateChange::from_glib(c))
176 };
177 ElementPostMessagePost("element-post-message-post") = |this, ts, e: *mut ffi::GstElement, r: glib::ffi::gboolean| {
178 let e = Element::from_glib_borrow(e);
179 this.element_post_message_post(ts, &e, bool::from_glib(r))
180 };
181 ElementPostMessagePre("element-post-message-pre") = |this, ts, e: *mut ffi::GstElement, m: *mut ffi::GstMessage| {
182 let e = Element::from_glib_borrow(e);
183 let m = Message::from_glib_borrow(m);
184 this.element_post_message_pre(ts, &e, &m)
185 };
186 ElementQueryPost("element-query-post") = |this, ts, e: *mut ffi::GstElement, q: *mut ffi::GstQuery, r: glib::ffi::gboolean| {
187 let e = Element::from_glib_borrow(e);
188 let q = QueryRef::from_ptr(q);
189 this.element_query_post(ts, &e, q, bool::from_glib(r))
190 };
191 ElementQueryPre("element-query-pre") = |this, ts, e: *mut ffi::GstElement, q: *mut ffi::GstQuery| {
192 let e = Element::from_glib_borrow(e);
193 let q = QueryRef::from_ptr(q);
194 this.element_query_pre(ts, &e, q)
195 };
196 // TODO: unclear what to do here as the `GstMiniObject` here is not fully initialized yet…
197 MiniObjectCreated("mini-object-created") = |this, ts, o: *mut ffi::GstMiniObject| {
198 this.mini_object_created(ts, std::ptr::NonNull::new_unchecked(o))
199 };
200 // TODO: unclear what to do here as the `GstMiniObject` here is no longer valid…
201 MiniObjectDestroyed("mini-object-destroyed") = |this, ts, o: *mut ffi::GstMiniObject| {
202 this.mini_object_destroyed(ts, std::ptr::NonNull::new_unchecked(o))
203 };
204 MiniObjectReffed("mini-object-reffed") = |this, ts, o: *mut ffi::GstMiniObject, rc: libc::c_int| {
205 let o = MiniObject::from_glib_borrow(o);
206 this.mini_object_reffed(ts, &o, rc)
207 };
208 MiniObjectUnreffed("mini-object-unreffed") = |this, ts, o: *mut ffi::GstMiniObject, rc: libc::c_int| {
209 let o = MiniObject::from_glib_borrow(o);
210 this.mini_object_unreffed(ts, &o, rc)
211 };
212 ObjectCreated("object-created") = |this, ts, o: *mut ffi::GstObject| {
213 let o = Object::from_glib_borrow(o);
214 this.object_created(ts, &o)
215 };
216 // TODO: unclear what to do here as the `GstObject` here is no longer valid…
217 ObjectDestroyed("object-destroyed") = |this, ts, o: *mut ffi::GstObject| {
218 this.object_destroyed(ts, std::ptr::NonNull::new_unchecked(o))
219 };
220 ObjectReffed("object-reffed") = |this, ts, o: *mut ffi::GstObject, rc: libc::c_int| {
221 let o = Object::from_glib_borrow(o);
222 this.object_reffed(ts, &o, rc)
223 };
224 ObjectUnreffed("object-unreffed") = |this, ts, o: *mut ffi::GstObject, rc: libc::c_int| {
225 let o = Object::from_glib_borrow(o);
226 this.object_unreffed(ts, &o, rc)
227 };
228 PadLinkPost("pad-link-post") = |this, ts, src: *mut ffi::GstPad, sink: *mut ffi::GstPad, r: ffi::GstPadLinkReturn| {
229 let src = Pad::from_glib_borrow(src);
230 let sink = Pad::from_glib_borrow(sink);
231 this.pad_link_post(ts, &src, &sink, try_from_glib(r))
232 };
233 PadLinkPre("pad-link-pre") = |this, ts, src: *mut ffi::GstPad, sink: *mut ffi::GstPad| {
234 let src = Pad::from_glib_borrow(src);
235 let sink = Pad::from_glib_borrow(sink);
236 this.pad_link_pre(ts, &src, &sink)
237 };
238 PadPullRangePost("pad-pull-range-post") = |this, ts, p: *mut ffi::GstPad, b: *mut ffi::GstBuffer, r: ffi::GstFlowReturn| {
239 let p = Pad::from_glib_borrow(p);
240 let res: Result::<FlowSuccess, FlowError> = try_from_glib(r);
241 match res {
242 Ok(_) => {
243 this.pad_pull_range_post(ts, &p, Ok(&from_glib_borrow(b)))
244 }
245 Err(err) => {
246 this.pad_pull_range_post(ts, &p, Err(err))
247 }
248 }
249 };
250 PadPullRangePre("pad-pull-range-pre") = |this, ts, p: *mut ffi::GstPad, o: u64, s: libc::c_uint| {
251 let p = Pad::from_glib_borrow(p);
252 this.pad_pull_range_pre(ts, &p, o, s)
253 };
254 PadPushEventPost("pad-push-event-post") = |this, ts, p: *mut ffi::GstPad, r: glib::ffi::gboolean| {
255 let p = Pad::from_glib_borrow(p);
256 this.pad_push_event_post(ts, &p, bool::from_glib(r))
257 };
258 PadPushEventPre("pad-push-event-pre") = |this, ts, p: *mut ffi::GstPad, e: *mut ffi::GstEvent| {
259 let p = Pad::from_glib_borrow(p);
260 let e = Event::from_glib_borrow(e);
261 this.pad_push_event_pre(ts, &p, &e)
262 };
263 PadPushListPost("pad-push-list-post") = |this, ts, p: *mut ffi::GstPad, r: ffi::GstFlowReturn| {
264 let p = Pad::from_glib_borrow(p);
265 this.pad_push_list_post(ts, &p, try_from_glib(r))
266 };
267 PadPushListPre("pad-push-list-pre") = |this, ts, p: *mut ffi::GstPad, bl: *mut ffi::GstBufferList| {
268 let p = Pad::from_glib_borrow(p);
269 let bl = BufferList::from_glib_borrow(bl);
270 this.pad_push_list_pre(ts, &p, &bl)
271 };
272 PadPushPost("pad-push-post") = |this, ts, p: *mut ffi::GstPad, r: ffi::GstFlowReturn| {
273 let p = Pad::from_glib_borrow(p);
274 this.pad_push_post(ts, &p, try_from_glib(r))
275 };
276 PadPushPre("pad-push-pre") = |this, ts, p: *mut ffi::GstPad, b: *mut ffi::GstBuffer| {
277 let p = Pad::from_glib_borrow(p);
278 let b = Buffer::from_glib_borrow(b);
279 this.pad_push_pre(ts, &p, &b)
280 };
281 #[cfg(feature = "v1_22")]
282 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
283 PadChainListPost("pad-chain-list-post") = |this, ts, p: *mut ffi::GstPad, r: ffi::GstFlowReturn| {
284 let p = Pad::from_glib_borrow(p);
285 this.pad_chain_list_post(ts, &p, try_from_glib(r))
286 };
287 #[cfg(feature = "v1_22")]
288 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
289 PadChainListPre("pad-chain-list-pre") = |this, ts, p: *mut ffi::GstPad, bl: *mut ffi::GstBufferList| {
290 let p = Pad::from_glib_borrow(p);
291 let bl = BufferList::from_glib_borrow(bl);
292 this.pad_chain_list_pre(ts, &p, &bl)
293 };
294 #[cfg(feature = "v1_22")]
295 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
296 PadChainPost("pad-chain-post") = |this, ts, p: *mut ffi::GstPad, r: ffi::GstFlowReturn| {
297 let p = Pad::from_glib_borrow(p);
298 this.pad_chain_post(ts, &p, try_from_glib(r))
299 };
300 #[cfg(feature = "v1_22")]
301 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
302 PadChainPre("pad-chain-pre") = |this, ts, p: *mut ffi::GstPad, b: *mut ffi::GstBuffer| {
303 let p = Pad::from_glib_borrow(p);
304 let b = Buffer::from_glib_borrow(b);
305 this.pad_chain_pre(ts, &p, &b)
306 };
307 PadQueryPost("pad-query-post") = |this, ts, p: *mut ffi::GstPad, q: *mut ffi::GstQuery, r: glib::ffi::gboolean| {
308 let p = Pad::from_glib_borrow(p);
309 let q = QueryRef::from_ptr(q);
310 this.pad_query_post(ts, &p, q, bool::from_glib(r))
311 };
312 PadQueryPre("pad-query-pre") = |this, ts, p: *mut ffi::GstPad, q: *mut ffi::GstQuery| {
313 let p = Pad::from_glib_borrow(p);
314 let q = QueryRef::from_ptr(q);
315 this.pad_query_pre(ts, &p, q)
316 };
317 PadUnlinkPost("pad-unlink-post") = |this, ts, src: *mut ffi::GstPad, sink: *mut ffi::GstPad, r: glib::ffi::gboolean| {
318 let src = Pad::from_glib_borrow(src);
319 let sink = Pad::from_glib_borrow(sink);
320 this.pad_unlink_post(ts, &src, &sink, bool::from_glib(r))
321 };
322 PadUnlinkPre("pad-unlink-pre") = |this, ts, src: *mut ffi::GstPad, sink: *mut ffi::GstPad| {
323 let src = Pad::from_glib_borrow(src);
324 let sink = Pad::from_glib_borrow(sink);
325 this.pad_unlink_pre(ts, &src, &sink)
326 };
327 #[cfg(feature = "v1_20")]
328 #[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
329 PluginFeatureLoaded("plugin-feature-loaded") = |this, ts, feature: *mut ffi::GstPluginFeature| {
330 let feature = crate::PluginFeature::from_glib_borrow(feature);
331 this.plugin_feature_loaded(ts, &feature)
332 };
333}
334