gstreamer_check/
harness.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::{mem, ops, path, ptr};
4
5use glib::translate::*;
6use gst::prelude::*;
7
8use crate::{ffi, TestClock};
9
10#[derive(Debug)]
11#[doc(alias = "GstHarness")]
12#[repr(transparent)]
13pub struct Harness(ptr::NonNull<ffi::GstHarness>);
14
15impl Drop for Harness {
16    #[inline]
17    fn drop(&mut self) {
18        unsafe {
19            ffi::gst_harness_teardown(self.0.as_ptr());
20        }
21    }
22}
23
24unsafe impl Send for Harness {}
25unsafe impl Sync for Harness {}
26
27impl Harness {
28    #[doc(alias = "gst_harness_add_element_full")]
29    pub fn add_element_full<P: IsA<gst::Element>>(
30        &mut self,
31        element: &P,
32        hsrc: Option<&gst::StaticPadTemplate>,
33        element_sinkpad_name: Option<&str>,
34        hsink: Option<&gst::StaticPadTemplate>,
35        element_srcpad_name: Option<&str>,
36    ) {
37        let element_sinkpad_name = element_sinkpad_name.to_glib_none();
38        let element_srcpad_name = element_srcpad_name.to_glib_none();
39        unsafe {
40            ffi::gst_harness_add_element_full(
41                self.0.as_ptr(),
42                element.as_ref().to_glib_none().0,
43                hsrc.to_glib_none().0 as *mut _,
44                element_sinkpad_name.0,
45                hsink.to_glib_none().0 as *mut _,
46                element_srcpad_name.0,
47            );
48        }
49    }
50
51    #[doc(alias = "gst_harness_add_element_sink_pad")]
52    pub fn add_element_sink_pad<P: IsA<gst::Pad>>(&mut self, sinkpad: &P) {
53        unsafe {
54            ffi::gst_harness_add_element_sink_pad(
55                self.0.as_ptr(),
56                sinkpad.as_ref().to_glib_none().0,
57            );
58        }
59    }
60
61    #[doc(alias = "gst_harness_add_element_src_pad")]
62    pub fn add_element_src_pad<P: IsA<gst::Pad>>(&mut self, srcpad: &P) {
63        unsafe {
64            ffi::gst_harness_add_element_src_pad(self.0.as_ptr(), srcpad.as_ref().to_glib_none().0);
65        }
66    }
67
68    #[doc(alias = "gst_harness_add_parse")]
69    pub fn add_parse(&mut self, launchline: &str) {
70        unsafe {
71            ffi::gst_harness_add_parse(self.0.as_ptr(), launchline.to_glib_none().0);
72        }
73    }
74
75    pub fn add_probe<F>(
76        &mut self,
77        element_name: &str,
78        pad_name: &str,
79        mask: gst::PadProbeType,
80        func: F,
81    ) where
82        F: Fn(&gst::Pad, &mut gst::PadProbeInfo) -> gst::PadProbeReturn + Send + Sync + 'static,
83    {
84        // Reimplementation of the C code so we don't have to duplicate all the callback code
85
86        let element = self.find_element(element_name).expect("Element not found");
87        let pad = element.static_pad(pad_name).expect("Pad not found");
88        pad.add_probe(mask, func);
89    }
90
91    #[cfg(feature = "v1_16")]
92    #[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))]
93    #[doc(alias = "gst_harness_add_propose_allocation_meta")]
94    pub fn add_propose_allocation_meta(
95        &mut self,
96        api: glib::types::Type,
97        params: Option<&gst::StructureRef>,
98    ) {
99        unsafe {
100            let params = params.map(|p| p.as_ptr()).unwrap_or(ptr::null_mut());
101            ffi::gst_harness_add_propose_allocation_meta(self.0.as_ptr(), api.into_glib(), params);
102        }
103    }
104
105    #[doc(alias = "gst_harness_add_sink")]
106    pub fn add_sink(&mut self, sink_element_name: &str) {
107        unsafe {
108            ffi::gst_harness_add_sink(self.0.as_ptr(), sink_element_name.to_glib_none().0);
109        }
110    }
111
112    #[doc(alias = "gst_harness_add_sink_harness")]
113    pub fn add_sink_harness(&mut self, sink_harness: Harness) {
114        unsafe {
115            let sink_harness = mem::ManuallyDrop::new(sink_harness);
116            ffi::gst_harness_add_sink_harness(self.0.as_ptr(), sink_harness.0.as_ptr());
117        }
118    }
119
120    #[doc(alias = "gst_harness_add_sink_parse")]
121    pub fn add_sink_parse(&mut self, launchline: &str) {
122        unsafe {
123            ffi::gst_harness_add_sink_parse(self.0.as_ptr(), launchline.to_glib_none().0);
124        }
125    }
126
127    #[doc(alias = "gst_harness_add_src")]
128    pub fn add_src(&mut self, src_element_name: &str, has_clock_wait: bool) {
129        unsafe {
130            ffi::gst_harness_add_src(
131                self.0.as_ptr(),
132                src_element_name.to_glib_none().0,
133                has_clock_wait.into_glib(),
134            );
135        }
136    }
137
138    #[doc(alias = "gst_harness_add_src_harness")]
139    pub fn add_src_harness(&mut self, src_harness: Harness, has_clock_wait: bool) {
140        unsafe {
141            let src_harness = mem::ManuallyDrop::new(src_harness);
142            ffi::gst_harness_add_src_harness(
143                self.0.as_ptr(),
144                src_harness.0.as_ptr(),
145                has_clock_wait.into_glib(),
146            );
147        }
148    }
149
150    #[doc(alias = "gst_harness_add_src_parse")]
151    pub fn add_src_parse(&mut self, launchline: &str, has_clock_wait: bool) {
152        unsafe {
153            ffi::gst_harness_add_src_parse(
154                self.0.as_ptr(),
155                launchline.to_glib_none().0,
156                has_clock_wait.into_glib(),
157            );
158        }
159    }
160
161    #[doc(alias = "gst_harness_buffers_in_queue")]
162    pub fn buffers_in_queue(&self) -> u32 {
163        unsafe { ffi::gst_harness_buffers_in_queue(self.0.as_ptr()) }
164    }
165
166    #[doc(alias = "gst_harness_buffers_received")]
167    pub fn buffers_received(&self) -> u32 {
168        unsafe { ffi::gst_harness_buffers_received(self.0.as_ptr()) }
169    }
170
171    #[doc(alias = "gst_harness_crank_multiple_clock_waits")]
172    pub fn crank_multiple_clock_waits(&mut self, waits: u32) -> Result<(), glib::BoolError> {
173        unsafe {
174            glib::result_from_gboolean!(
175                ffi::gst_harness_crank_multiple_clock_waits(self.0.as_ptr(), waits),
176                "Failed to crank multiple clock waits",
177            )
178        }
179    }
180
181    #[doc(alias = "gst_harness_crank_single_clock_wait")]
182    pub fn crank_single_clock_wait(&mut self) -> Result<(), glib::BoolError> {
183        unsafe {
184            glib::result_from_gboolean!(
185                ffi::gst_harness_crank_single_clock_wait(self.0.as_ptr()),
186                "Failed to crank single clock wait",
187            )
188        }
189    }
190
191    #[doc(alias = "gst_harness_create_buffer")]
192    pub fn create_buffer(&mut self, size: usize) -> Result<gst::Buffer, glib::BoolError> {
193        unsafe {
194            Option::<_>::from_glib_full(ffi::gst_harness_create_buffer(self.0.as_ptr(), size))
195                .ok_or_else(|| glib::bool_error!("Failed to create new buffer"))
196        }
197    }
198
199    #[doc(alias = "gst_harness_dump_to_file")]
200    pub fn dump_to_file(&mut self, filename: impl AsRef<path::Path>) {
201        let filename = filename.as_ref();
202        unsafe {
203            ffi::gst_harness_dump_to_file(self.0.as_ptr(), filename.to_glib_none().0);
204        }
205    }
206
207    #[doc(alias = "gst_harness_events_in_queue")]
208    pub fn events_in_queue(&self) -> u32 {
209        unsafe { ffi::gst_harness_events_in_queue(self.0.as_ptr()) }
210    }
211
212    #[doc(alias = "gst_harness_events_received")]
213    pub fn events_received(&self) -> u32 {
214        unsafe { ffi::gst_harness_events_received(self.0.as_ptr()) }
215    }
216
217    #[doc(alias = "gst_harness_find_element")]
218    pub fn find_element(&mut self, element_name: &str) -> Option<gst::Element> {
219        unsafe {
220            // Work around https://gitlab.freedesktop.org/gstreamer/gstreamer/merge_requests/31
221            let ptr = ffi::gst_harness_find_element(self.0.as_ptr(), element_name.to_glib_none().0);
222
223            if ptr.is_null() {
224                return None;
225            }
226
227            // Clear floating flag if it is set
228            if glib::gobject_ffi::g_object_is_floating(ptr as *mut _) != glib::ffi::GFALSE {
229                glib::gobject_ffi::g_object_ref_sink(ptr as *mut _);
230            }
231
232            from_glib_full(ptr)
233        }
234    }
235
236    //pub fn get(&mut self, element_name: &str, first_property_name: &str, : /*Unknown conversion*//*Unimplemented*/Fundamental: VarArgs) {
237    //    unsafe { TODO: call ffi::gst_harness_get() }
238    //}
239
240    //pub fn get_allocator(&mut self, allocator: /*Ignored*/gst::Allocator, params: /*Ignored*/gst::AllocationParams) {
241    //    unsafe { TODO: call ffi::gst_harness_get_allocator() }
242    //}
243
244    #[doc(alias = "get_last_pushed_timestamp")]
245    #[doc(alias = "gst_harness_get_last_pushed_timestamp")]
246    pub fn last_pushed_timestamp(&self) -> Option<gst::ClockTime> {
247        unsafe { from_glib(ffi::gst_harness_get_last_pushed_timestamp(self.0.as_ptr())) }
248    }
249
250    #[doc(alias = "get_testclock")]
251    #[doc(alias = "gst_harness_get_testclock")]
252    pub fn testclock(&self) -> Option<TestClock> {
253        unsafe { from_glib_full(ffi::gst_harness_get_testclock(self.0.as_ptr())) }
254    }
255
256    #[doc(alias = "gst_harness_play")]
257    pub fn play(&mut self) {
258        unsafe {
259            ffi::gst_harness_play(self.0.as_ptr());
260        }
261    }
262
263    #[doc(alias = "gst_harness_pull")]
264    pub fn pull(&mut self) -> Result<gst::Buffer, glib::BoolError> {
265        unsafe {
266            Option::<_>::from_glib_full(ffi::gst_harness_pull(self.0.as_ptr()))
267                .ok_or_else(|| glib::bool_error!("Failed to pull buffer"))
268        }
269    }
270
271    #[cfg(feature = "v1_18")]
272    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
273    #[doc(alias = "gst_harness_pull_until_eos")]
274    pub fn pull_until_eos(&mut self) -> Result<Option<gst::Buffer>, glib::BoolError> {
275        unsafe {
276            let mut buffer = ptr::null_mut();
277            let res = ffi::gst_harness_pull_until_eos(self.0.as_ptr(), &mut buffer);
278            if from_glib(res) {
279                Ok(from_glib_full(buffer))
280            } else {
281                Err(glib::bool_error!("Failed to pull buffer or EOS"))
282            }
283        }
284    }
285
286    #[doc(alias = "gst_harness_pull_event")]
287    pub fn pull_event(&mut self) -> Result<gst::Event, glib::BoolError> {
288        unsafe {
289            Option::<_>::from_glib_full(ffi::gst_harness_pull_event(self.0.as_ptr()))
290                .ok_or_else(|| glib::bool_error!("Failed to pull event"))
291        }
292    }
293
294    #[doc(alias = "gst_harness_pull_upstream_event")]
295    pub fn pull_upstream_event(&mut self) -> Result<gst::Event, glib::BoolError> {
296        unsafe {
297            Option::<_>::from_glib_full(ffi::gst_harness_pull_upstream_event(self.0.as_ptr()))
298                .ok_or_else(|| glib::bool_error!("Failed to pull event"))
299        }
300    }
301
302    #[doc(alias = "gst_harness_push")]
303    pub fn push(&mut self, buffer: gst::Buffer) -> Result<gst::FlowSuccess, gst::FlowError> {
304        unsafe {
305            try_from_glib(ffi::gst_harness_push(
306                self.0.as_ptr(),
307                buffer.into_glib_ptr(),
308            ))
309        }
310    }
311
312    #[doc(alias = "gst_harness_push_and_pull")]
313    pub fn push_and_pull(&mut self, buffer: gst::Buffer) -> Result<gst::Buffer, glib::BoolError> {
314        unsafe {
315            Option::<_>::from_glib_full(ffi::gst_harness_push_and_pull(
316                self.0.as_ptr(),
317                buffer.into_glib_ptr(),
318            ))
319            .ok_or_else(|| glib::bool_error!("Failed to push and pull buffer"))
320        }
321    }
322
323    #[doc(alias = "gst_harness_push_event")]
324    pub fn push_event(&mut self, event: gst::Event) -> bool {
325        unsafe {
326            from_glib(ffi::gst_harness_push_event(
327                self.0.as_ptr(),
328                event.into_glib_ptr(),
329            ))
330        }
331    }
332
333    #[doc(alias = "gst_harness_push_from_src")]
334    pub fn push_from_src(&mut self) -> Result<gst::FlowSuccess, gst::FlowError> {
335        unsafe { try_from_glib(ffi::gst_harness_push_from_src(self.0.as_ptr())) }
336    }
337
338    #[doc(alias = "gst_harness_push_to_sink")]
339    pub fn push_to_sink(&mut self) -> Result<gst::FlowSuccess, gst::FlowError> {
340        unsafe { try_from_glib(ffi::gst_harness_push_to_sink(self.0.as_ptr())) }
341    }
342
343    #[doc(alias = "gst_harness_push_upstream_event")]
344    pub fn push_upstream_event(&mut self, event: gst::Event) -> bool {
345        unsafe {
346            from_glib(ffi::gst_harness_push_upstream_event(
347                self.0.as_ptr(),
348                event.into_glib_ptr(),
349            ))
350        }
351    }
352
353    #[doc(alias = "gst_harness_query_latency")]
354    pub fn query_latency(&self) -> Option<gst::ClockTime> {
355        unsafe { from_glib(ffi::gst_harness_query_latency(self.0.as_ptr())) }
356    }
357
358    //pub fn set(&mut self, element_name: &str, first_property_name: &str, : /*Unknown conversion*//*Unimplemented*/Fundamental: VarArgs) {
359    //    unsafe { TODO: call ffi::gst_harness_set() }
360    //}
361
362    #[doc(alias = "gst_harness_set_blocking_push_mode")]
363    pub fn set_blocking_push_mode(&mut self) {
364        unsafe {
365            ffi::gst_harness_set_blocking_push_mode(self.0.as_ptr());
366        }
367    }
368
369    #[doc(alias = "gst_harness_set_caps")]
370    pub fn set_caps(&mut self, in_: gst::Caps, out: gst::Caps) {
371        unsafe {
372            ffi::gst_harness_set_caps(self.0.as_ptr(), in_.into_glib_ptr(), out.into_glib_ptr());
373        }
374    }
375
376    #[doc(alias = "gst_harness_set_caps_str")]
377    pub fn set_caps_str(&mut self, in_: &str, out: &str) {
378        unsafe {
379            ffi::gst_harness_set_caps_str(
380                self.0.as_ptr(),
381                in_.to_glib_none().0,
382                out.to_glib_none().0,
383            );
384        }
385    }
386
387    #[doc(alias = "gst_harness_set_drop_buffers")]
388    pub fn set_drop_buffers(&mut self, drop_buffers: bool) {
389        unsafe {
390            ffi::gst_harness_set_drop_buffers(self.0.as_ptr(), drop_buffers.into_glib());
391        }
392    }
393
394    #[doc(alias = "gst_harness_set_forwarding")]
395    pub fn set_forwarding(&mut self, forwarding: bool) {
396        unsafe {
397            ffi::gst_harness_set_forwarding(self.0.as_ptr(), forwarding.into_glib());
398        }
399    }
400
401    #[doc(alias = "gst_harness_set_live")]
402    #[cfg(feature = "v1_20")]
403    #[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
404    pub fn set_live(&mut self, is_live: bool) {
405        unsafe { ffi::gst_harness_set_live(self.0.as_ptr(), is_live.into_glib()) }
406    }
407
408    //pub fn set_propose_allocator<P: IsA<gst::Allocator>>(&mut self, allocator: Option<&P>, params: Option<&gst::AllocationParams>) {
409    //    unsafe { TODO: call ffi::gst_harness_set_propose_allocator() }
410    //}
411
412    #[doc(alias = "gst_harness_set_sink_caps")]
413    pub fn set_sink_caps(&mut self, caps: gst::Caps) {
414        unsafe {
415            ffi::gst_harness_set_sink_caps(self.0.as_ptr(), caps.into_glib_ptr());
416        }
417    }
418
419    #[doc(alias = "gst_harness_set_sink_caps_str")]
420    pub fn set_sink_caps_str(&mut self, str: &str) {
421        unsafe {
422            ffi::gst_harness_set_sink_caps_str(self.0.as_ptr(), str.to_glib_none().0);
423        }
424    }
425
426    #[doc(alias = "gst_harness_set_src_caps")]
427    pub fn set_src_caps(&mut self, caps: gst::Caps) {
428        unsafe {
429            ffi::gst_harness_set_src_caps(self.0.as_ptr(), caps.into_glib_ptr());
430        }
431    }
432
433    #[doc(alias = "gst_harness_set_src_caps_str")]
434    pub fn set_src_caps_str(&mut self, str: &str) {
435        unsafe {
436            ffi::gst_harness_set_src_caps_str(self.0.as_ptr(), str.to_glib_none().0);
437        }
438    }
439
440    #[doc(alias = "gst_harness_set_time")]
441    pub fn set_time(&mut self, time: gst::ClockTime) -> Result<(), glib::BoolError> {
442        unsafe {
443            glib::result_from_gboolean!(
444                ffi::gst_harness_set_time(self.0.as_ptr(), time.into_glib()),
445                "Failed to set time",
446            )
447        }
448    }
449
450    #[doc(alias = "gst_harness_set_upstream_latency")]
451    pub fn set_upstream_latency(&mut self, latency: gst::ClockTime) {
452        unsafe {
453            ffi::gst_harness_set_upstream_latency(self.0.as_ptr(), latency.into_glib());
454        }
455    }
456
457    #[doc(alias = "gst_harness_sink_push_many")]
458    pub fn sink_push_many(&mut self, pushes: u32) -> Result<gst::FlowSuccess, gst::FlowError> {
459        unsafe {
460            try_from_glib(ffi::gst_harness_sink_push_many(
461                self.0.as_ptr(),
462                pushes as i32,
463            ))
464        }
465    }
466
467    #[doc(alias = "gst_harness_src_crank_and_push_many")]
468    pub fn src_crank_and_push_many(
469        &mut self,
470        cranks: u32,
471        pushes: u32,
472    ) -> Result<gst::FlowSuccess, gst::FlowError> {
473        unsafe {
474            try_from_glib(ffi::gst_harness_src_crank_and_push_many(
475                self.0.as_ptr(),
476                cranks as i32,
477                pushes as i32,
478            ))
479        }
480    }
481
482    #[doc(alias = "gst_harness_src_push_event")]
483    pub fn src_push_event(&mut self) -> bool {
484        unsafe { from_glib(ffi::gst_harness_src_push_event(self.0.as_ptr())) }
485    }
486
487    //pub fn stress_custom_start<'a, P: Into<Option<&'a /*Ignored*/glib::Func>>, Q: Into<Option</*Unimplemented*/Fundamental: Pointer>>>(&mut self, init: P, callback: /*Unknown conversion*//*Unimplemented*/Func, data: Q, sleep: libc::c_ulong) -> /*Ignored*/Option<HarnessThread> {
488    //    unsafe { TODO: call ffi::gst_harness_stress_custom_start() }
489    //}
490
491    //pub fn stress_property_start_full(&mut self, name: &str, value: /*Ignored*/&glib::Value, sleep: libc::c_ulong) -> /*Ignored*/Option<HarnessThread> {
492    //    unsafe { TODO: call ffi::gst_harness_stress_property_start_full() }
493    //}
494
495    //pub fn stress_push_buffer_start_full(&mut self, caps: &mut gst::Caps, segment: /*Ignored*/&gst::Segment, buf: &mut gst::Buffer, sleep: libc::c_ulong) -> /*Ignored*/Option<HarnessThread> {
496    //    unsafe { TODO: call ffi::gst_harness_stress_push_buffer_start_full() }
497    //}
498
499    //pub fn stress_push_buffer_with_cb_start_full<P: Into<Option</*Unimplemented*/Fundamental: Pointer>>>(&mut self, caps: &mut gst::Caps, segment: /*Ignored*/&gst::Segment, func: /*Unknown conversion*//*Unimplemented*/HarnessPrepareBufferFunc, data: P, notify: /*Unknown conversion*//*Unimplemented*/DestroyNotify, sleep: libc::c_ulong) -> /*Ignored*/Option<HarnessThread> {
500    //    unsafe { TODO: call ffi::gst_harness_stress_push_buffer_with_cb_start_full() }
501    //}
502
503    //pub fn stress_push_event_start_full(&mut self, event: &mut gst::Event, sleep: libc::c_ulong) -> /*Ignored*/Option<HarnessThread> {
504    //    unsafe { TODO: call ffi::gst_harness_stress_push_event_start_full() }
505    //}
506
507    //pub fn stress_push_event_with_cb_start_full<P: Into<Option</*Unimplemented*/Fundamental: Pointer>>>(&mut self, func: /*Unknown conversion*//*Unimplemented*/HarnessPrepareEventFunc, data: P, notify: /*Unknown conversion*//*Unimplemented*/DestroyNotify, sleep: libc::c_ulong) -> /*Ignored*/Option<HarnessThread> {
508    //    unsafe { TODO: call ffi::gst_harness_stress_push_event_with_cb_start_full() }
509    //}
510
511    //pub fn stress_push_upstream_event_start_full(&mut self, event: &mut gst::Event, sleep: libc::c_ulong) -> /*Ignored*/Option<HarnessThread> {
512    //    unsafe { TODO: call ffi::gst_harness_stress_push_upstream_event_start_full() }
513    //}
514
515    //pub fn stress_push_upstream_event_with_cb_start_full<P: Into<Option</*Unimplemented*/Fundamental: Pointer>>>(&mut self, func: /*Unknown conversion*//*Unimplemented*/HarnessPrepareEventFunc, data: P, notify: /*Unknown conversion*//*Unimplemented*/DestroyNotify, sleep: libc::c_ulong) -> /*Ignored*/Option<HarnessThread> {
516    //    unsafe { TODO: call ffi::gst_harness_stress_push_upstream_event_with_cb_start_full() }
517    //}
518
519    //pub fn stress_requestpad_start_full(&mut self, templ: /*Ignored*/&gst::PadTemplate, name: &str, caps: &mut gst::Caps, release: bool, sleep: libc::c_ulong) -> /*Ignored*/Option<HarnessThread> {
520    //    unsafe { TODO: call ffi::gst_harness_stress_requestpad_start_full() }
521    //}
522
523    //pub fn stress_statechange_start_full(&mut self, sleep: libc::c_ulong) -> /*Ignored*/Option<HarnessThread> {
524    //    unsafe { TODO: call ffi::gst_harness_stress_statechange_start_full() }
525    //}
526
527    #[doc(alias = "gst_harness_take_all_data_as_buffer")]
528    pub fn take_all_data_as_buffer(&mut self) -> Result<gst::Buffer, glib::BoolError> {
529        unsafe {
530            Option::<_>::from_glib_full(ffi::gst_harness_take_all_data_as_buffer(self.0.as_ptr()))
531                .ok_or_else(|| glib::bool_error!("Failed to take all data as buffer"))
532        }
533    }
534
535    #[doc(alias = "gst_harness_take_all_data_as_bytes")]
536    pub fn take_all_data_as_bytes(&mut self) -> Result<glib::Bytes, glib::BoolError> {
537        unsafe {
538            Option::<_>::from_glib_full(ffi::gst_harness_take_all_data_as_bytes(self.0.as_ptr()))
539                .ok_or_else(|| glib::bool_error!("Failed to take all data as bytes"))
540        }
541    }
542
543    #[doc(alias = "gst_harness_try_pull")]
544    pub fn try_pull(&mut self) -> Option<gst::Buffer> {
545        unsafe { from_glib_full(ffi::gst_harness_try_pull(self.0.as_ptr())) }
546    }
547
548    #[doc(alias = "gst_harness_try_pull_event")]
549    pub fn try_pull_event(&mut self) -> Option<gst::Event> {
550        unsafe { from_glib_full(ffi::gst_harness_try_pull_event(self.0.as_ptr())) }
551    }
552
553    #[doc(alias = "gst_harness_try_pull_upstream_event")]
554    pub fn try_pull_upstream_event(&mut self) -> Option<gst::Event> {
555        unsafe { from_glib_full(ffi::gst_harness_try_pull_upstream_event(self.0.as_ptr())) }
556    }
557
558    #[doc(alias = "gst_harness_upstream_events_in_queue")]
559    pub fn upstream_events_in_queue(&self) -> u32 {
560        unsafe { ffi::gst_harness_upstream_events_in_queue(self.0.as_ptr()) }
561    }
562
563    #[doc(alias = "gst_harness_upstream_events_received")]
564    pub fn upstream_events_received(&self) -> u32 {
565        unsafe { ffi::gst_harness_upstream_events_received(self.0.as_ptr()) }
566    }
567
568    #[doc(alias = "gst_harness_use_systemclock")]
569    pub fn use_systemclock(&mut self) {
570        unsafe {
571            ffi::gst_harness_use_systemclock(self.0.as_ptr());
572        }
573    }
574
575    #[doc(alias = "gst_harness_use_testclock")]
576    pub fn use_testclock(&mut self) {
577        unsafe {
578            ffi::gst_harness_use_testclock(self.0.as_ptr());
579        }
580    }
581
582    #[doc(alias = "gst_harness_wait_for_clock_id_waits")]
583    pub fn wait_for_clock_id_waits(
584        &mut self,
585        waits: u32,
586        timeout: u32,
587    ) -> Result<(), glib::BoolError> {
588        unsafe {
589            glib::result_from_gboolean!(
590                ffi::gst_harness_wait_for_clock_id_waits(self.0.as_ptr(), waits, timeout),
591                "Failed to wait for clock id waits",
592            )
593        }
594    }
595
596    #[inline]
597    unsafe fn from_glib_full(ptr: *mut ffi::GstHarness) -> Harness {
598        debug_assert!(!ptr.is_null());
599
600        Harness(ptr::NonNull::new_unchecked(ptr))
601    }
602
603    #[doc(alias = "gst_harness_new")]
604    pub fn new(element_name: &str) -> Harness {
605        assert_initialized_main_thread!();
606        unsafe { Self::from_glib_full(ffi::gst_harness_new(element_name.to_glib_none().0)) }
607    }
608
609    #[doc(alias = "gst_harness_new_empty")]
610    pub fn new_empty() -> Harness {
611        assert_initialized_main_thread!();
612        unsafe { Self::from_glib_full(ffi::gst_harness_new_empty()) }
613    }
614
615    #[doc(alias = "gst_harness_new_full")]
616    pub fn new_full<P: IsA<gst::Element>>(
617        element: &P,
618        hsrc: Option<&gst::StaticPadTemplate>,
619        element_sinkpad_name: Option<&str>,
620        hsink: Option<&gst::StaticPadTemplate>,
621        element_srcpad_name: Option<&str>,
622    ) -> Harness {
623        assert_initialized_main_thread!();
624        let element_sinkpad_name = element_sinkpad_name.to_glib_none();
625        let element_srcpad_name = element_srcpad_name.to_glib_none();
626        unsafe {
627            Self::from_glib_full(ffi::gst_harness_new_full(
628                element.as_ref().to_glib_none().0,
629                hsrc.to_glib_none().0 as *mut _,
630                element_sinkpad_name.0,
631                hsink.to_glib_none().0 as *mut _,
632                element_srcpad_name.0,
633            ))
634        }
635    }
636
637    #[doc(alias = "gst_harness_new_parse")]
638    pub fn new_parse(launchline: &str) -> Harness {
639        assert_initialized_main_thread!();
640        unsafe { Self::from_glib_full(ffi::gst_harness_new_parse(launchline.to_glib_none().0)) }
641    }
642
643    #[doc(alias = "gst_harness_new_with_element")]
644    pub fn with_element<P: IsA<gst::Element>>(
645        element: &P,
646        element_sinkpad_name: Option<&str>,
647        element_srcpad_name: Option<&str>,
648    ) -> Harness {
649        skip_assert_initialized!();
650        let element_sinkpad_name = element_sinkpad_name.to_glib_none();
651        let element_srcpad_name = element_srcpad_name.to_glib_none();
652        unsafe {
653            Self::from_glib_full(ffi::gst_harness_new_with_element(
654                element.as_ref().to_glib_none().0,
655                element_sinkpad_name.0,
656                element_srcpad_name.0,
657            ))
658        }
659    }
660
661    #[doc(alias = "gst_harness_new_with_padnames")]
662    pub fn with_padnames(
663        element_name: &str,
664        element_sinkpad_name: Option<&str>,
665        element_srcpad_name: Option<&str>,
666    ) -> Harness {
667        assert_initialized_main_thread!();
668        let element_sinkpad_name = element_sinkpad_name.to_glib_none();
669        let element_srcpad_name = element_srcpad_name.to_glib_none();
670        unsafe {
671            Self::from_glib_full(ffi::gst_harness_new_with_padnames(
672                element_name.to_glib_none().0,
673                element_sinkpad_name.0,
674                element_srcpad_name.0,
675            ))
676        }
677    }
678
679    #[doc(alias = "gst_harness_new_with_templates")]
680    pub fn with_templates(
681        element_name: &str,
682        hsrc: Option<&gst::StaticPadTemplate>,
683        hsink: Option<&gst::StaticPadTemplate>,
684    ) -> Harness {
685        assert_initialized_main_thread!();
686        unsafe {
687            Self::from_glib_full(ffi::gst_harness_new_with_templates(
688                element_name.to_glib_none().0,
689                hsrc.to_glib_none().0 as *mut _,
690                hsink.to_glib_none().0 as *mut _,
691            ))
692        }
693    }
694
695    //pub fn stress_thread_stop(t: /*Ignored*/&mut HarnessThread) -> u32 {
696    //    unsafe { TODO: call ffi::gst_harness_stress_thread_stop() }
697    //}
698
699    #[doc(alias = "get_element")]
700    pub fn element(&self) -> Option<gst::Element> {
701        unsafe {
702            // Work around https://gitlab.freedesktop.org/gstreamer/gstreamer/merge_requests/31
703            let ptr = (*self.0.as_ptr()).element;
704
705            if ptr.is_null() {
706                return None;
707            }
708
709            // Clear floating flag if it is set
710            if glib::gobject_ffi::g_object_is_floating(ptr as *mut _) != glib::ffi::GFALSE {
711                glib::gobject_ffi::g_object_ref_sink(ptr as *mut _);
712            }
713
714            from_glib_none(ptr)
715        }
716    }
717
718    #[doc(alias = "get_sinkpad")]
719    pub fn sinkpad(&self) -> Option<gst::Pad> {
720        unsafe {
721            // Work around https://gitlab.freedesktop.org/gstreamer/gstreamer/merge_requests/31
722            let ptr = (*self.0.as_ptr()).sinkpad;
723
724            if ptr.is_null() {
725                return None;
726            }
727
728            // Clear floating flag if it is set
729            if glib::gobject_ffi::g_object_is_floating(ptr as *mut _) != glib::ffi::GFALSE {
730                glib::gobject_ffi::g_object_ref_sink(ptr as *mut _);
731            }
732
733            from_glib_none(ptr)
734        }
735    }
736
737    #[doc(alias = "get_srcpad")]
738    pub fn srcpad(&self) -> Option<gst::Pad> {
739        unsafe {
740            // Work around https://gitlab.freedesktop.org/gstreamer/gstreamer/merge_requests/31
741            let ptr = (*self.0.as_ptr()).srcpad;
742
743            if ptr.is_null() {
744                return None;
745            }
746
747            // Clear floating flag if it is set
748            if glib::gobject_ffi::g_object_is_floating(ptr as *mut _) != glib::ffi::GFALSE {
749                glib::gobject_ffi::g_object_ref_sink(ptr as *mut _);
750            }
751
752            from_glib_none(ptr)
753        }
754    }
755
756    #[doc(alias = "get_sink_harness")]
757    pub fn sink_harness(&self) -> Option<Ref<'_>> {
758        unsafe {
759            if (*self.0.as_ptr()).sink_harness.is_null() {
760                None
761            } else {
762                Some(Ref(
763                    &*((&(*self.0.as_ptr()).sink_harness) as *const *mut ffi::GstHarness
764                        as *const Harness),
765                ))
766            }
767        }
768    }
769
770    #[doc(alias = "get_src_harness")]
771    pub fn src_harness(&self) -> Option<Ref<'_>> {
772        unsafe {
773            if (*self.0.as_ptr()).src_harness.is_null() {
774                None
775            } else {
776                Some(Ref(
777                    &*((&(*self.0.as_ptr()).src_harness) as *const *mut ffi::GstHarness
778                        as *const Harness),
779                ))
780            }
781        }
782    }
783
784    #[doc(alias = "get_mut_sink_harness")]
785    pub fn sink_harness_mut(&mut self) -> Option<RefMut<'_>> {
786        unsafe {
787            if (*self.0.as_ptr()).sink_harness.is_null() {
788                None
789            } else {
790                Some(RefMut(
791                    &mut *((&mut (*self.0.as_ptr()).sink_harness) as *mut *mut ffi::GstHarness
792                        as *mut Harness),
793                ))
794            }
795        }
796    }
797
798    #[doc(alias = "get_mut_src_harness")]
799    pub fn src_harness_mut(&mut self) -> Option<RefMut<'_>> {
800        unsafe {
801            if (*self.0.as_ptr()).src_harness.is_null() {
802                None
803            } else {
804                Some(RefMut(
805                    &mut *((&mut (*self.0.as_ptr()).src_harness) as *mut *mut ffi::GstHarness
806                        as *mut Harness),
807                ))
808            }
809        }
810    }
811}
812
813#[derive(Debug)]
814pub struct Ref<'a>(&'a Harness);
815
816impl ops::Deref for Ref<'_> {
817    type Target = Harness;
818
819    #[inline]
820    fn deref(&self) -> &Harness {
821        self.0
822    }
823}
824
825#[derive(Debug)]
826pub struct RefMut<'a>(&'a mut Harness);
827
828impl ops::Deref for RefMut<'_> {
829    type Target = Harness;
830
831    #[inline]
832    fn deref(&self) -> &Harness {
833        self.0
834    }
835}
836
837impl ops::DerefMut for RefMut<'_> {
838    #[inline]
839    fn deref_mut(&mut self) -> &mut Harness {
840        self.0
841    }
842}
843
844#[cfg(test)]
845mod tests {
846    use super::*;
847
848    #[test]
849    fn test_identity_push_pull() {
850        gst::init().unwrap();
851
852        let mut h = Harness::new("identity");
853        h.set_src_caps_str("application/test");
854        let buf = gst::Buffer::new();
855        let buf = h.push_and_pull(buf);
856        assert!(buf.is_ok());
857    }
858}