1 | // Take a look at the license at the top of the repository in the LICENSE file. |
2 | |
3 | use glib::{prelude::*, subclass::prelude::*, translate::*}; |
4 | |
5 | use super::prelude::*; |
6 | use 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)] |
13 | pub 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 | |
86 | unsafe impl<T: TracerImpl> IsSubclassable<T> for Tracer {} |
87 | |
88 | pub 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 | |
96 | macro_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 | |
135 | define_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 | |