gstreamer_check/auto/
test_clock.rs

1// This file was generated by gir (https://github.com/gtk-rs/gir)
2// from gir-files (https://github.com/gtk-rs/gir-files)
3// from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git)
4// DO NOT EDIT
5
6use crate::ffi;
7use glib::{
8    prelude::*,
9    signal::{connect_raw, SignalHandlerId},
10    translate::*,
11};
12use std::boxed::Box as Box_;
13
14glib::wrapper! {
15    /// GstTestClock is an implementation of [`gst::Clock`][crate::gst::Clock] which has different
16    /// behaviour compared to [`gst::SystemClock`][crate::gst::SystemClock]. Time for [`gst::SystemClock`][crate::gst::SystemClock] advances
17    /// according to the system time, while time for [`TestClock`][crate::TestClock] changes only
18    /// when [`set_time()`][Self::set_time()] or [`advance_time()`][Self::advance_time()] are
19    /// called. [`TestClock`][crate::TestClock] provides unit tests with the possibility to
20    /// precisely advance the time in a deterministic manner, independent of the
21    /// system time or any other external factors.
22    ///
23    /// ## Advancing the time of a [`TestClock`][crate::TestClock]
24    ///
25    ///
26    ///
27    /// **⚠️ The following code is in C ⚠️**
28    ///
29    /// ```C
30    ///   #include <gst/gst.h>
31    ///   #include <gst/check/gsttestclock.h>
32    ///
33    ///   GstClock *clock;
34    ///   GstTestClock *test_clock;
35    ///
36    ///   clock = gst_test_clock_new ();
37    ///   test_clock = GST_TEST_CLOCK (clock);
38    ///   GST_INFO ("Time: %" GST_TIME_FORMAT, GST_TIME_ARGS (gst_clock_get_time (clock)));
39    ///   gst_test_clock_advance_time ( test_clock, 1 * GST_SECOND);
40    ///   GST_INFO ("Time: %" GST_TIME_FORMAT, GST_TIME_ARGS (gst_clock_get_time (clock)));
41    ///   g_usleep (10 * G_USEC_PER_SEC);
42    ///   GST_INFO ("Time: %" GST_TIME_FORMAT, GST_TIME_ARGS (gst_clock_get_time (clock)));
43    ///   gst_test_clock_set_time (test_clock, 42 * GST_SECOND);
44    ///   GST_INFO ("Time: %" GST_TIME_FORMAT, GST_TIME_ARGS (gst_clock_get_time (clock)));
45    ///   ...
46    /// ```
47    ///
48    /// [`gst::Clock`][crate::gst::Clock] allows for setting up single shot or periodic clock notifications
49    /// as well as waiting for these notifications synchronously (using
50    /// `gst_clock_id_wait()`) or asynchronously (using `gst_clock_id_wait_async()` or
51    /// `gst_clock_id_wait_async()`). This is used by many GStreamer elements,
52    /// among them `GstBaseSrc` and `GstBaseSink`.
53    ///
54    /// [`TestClock`][crate::TestClock] keeps track of these clock notifications. By calling
55    /// [`wait_for_next_pending_id()`][Self::wait_for_next_pending_id()] or
56    /// [`wait_for_multiple_pending_ids()`][Self::wait_for_multiple_pending_ids()] a unit tests may wait for the
57    /// next one or several clock notifications to be requested. Additionally unit
58    /// tests may release blocked waits in a controlled fashion by calling
59    /// [`process_next_clock_id()`][Self::process_next_clock_id()]. This way a unit test can control the
60    /// inaccuracy (jitter) of clock notifications, since the test can decide to
61    /// release blocked waits when the clock time has advanced exactly to, or past,
62    /// the requested clock notification time.
63    ///
64    /// There are also interfaces for determining if a notification belongs to a
65    /// [`TestClock`][crate::TestClock] or not, as well as getting the number of requested clock
66    /// notifications so far.
67    ///
68    /// N.B.: When a unit test waits for a certain amount of clock notifications to
69    /// be requested in [`wait_for_next_pending_id()`][Self::wait_for_next_pending_id()] or
70    /// [`wait_for_multiple_pending_ids()`][Self::wait_for_multiple_pending_ids()] then these functions may block
71    /// for a long time. If they block forever then the expected clock notifications
72    /// were never requested from [`TestClock`][crate::TestClock], and so the assumptions in the code
73    /// of the unit test are wrong. The unit test case runner in gstcheck is
74    /// expected to catch these cases either by the default test case timeout or the
75    /// one set for the unit test by calling tcase_set_timeout\(\).
76    ///
77    /// The sample code below assumes that the element under test will delay a
78    /// buffer pushed on the source pad by some latency until it arrives on the sink
79    /// pad. Moreover it is assumed that the element will at some point call
80    /// `gst_clock_id_wait()` to synchronously wait for a specific time. The first
81    /// buffer sent will arrive exactly on time only delayed by the latency. The
82    /// second buffer will arrive a little late (7ms) due to simulated jitter in the
83    /// clock notification.
84    ///
85    /// ## Demonstration of how to work with clock notifications and [`TestClock`][crate::TestClock]
86    ///
87    ///
88    ///
89    /// **⚠️ The following code is in C ⚠️**
90    ///
91    /// ```C
92    ///   #include <gst/gst.h>
93    ///   #include <gst/check/gstcheck.h>
94    ///   #include <gst/check/gsttestclock.h>
95    ///
96    ///   GstClockTime latency;
97    ///   GstElement *element;
98    ///   GstPad *srcpad;
99    ///   GstClock *clock;
100    ///   GstTestClock *test_clock;
101    ///   GstBuffer buf;
102    ///   GstClockID pending_id;
103    ///   GstClockID processed_id;
104    ///
105    ///   latency = 42 * GST_MSECOND;
106    ///   element = create_element (latency, ...);
107    ///   srcpad = get_source_pad (element);
108    ///
109    ///   clock = gst_test_clock_new ();
110    ///   test_clock = GST_TEST_CLOCK (clock);
111    ///   gst_element_set_clock (element, clock);
112    ///
113    ///   GST_INFO ("Set time, create and push the first buffer\n");
114    ///   gst_test_clock_set_time (test_clock, 0);
115    ///   buf = create_test_buffer (gst_clock_get_time (clock), ...);
116    ///   gst_assert_cmpint (gst_pad_push (srcpad, buf), ==, GST_FLOW_OK);
117    ///
118    ///   GST_INFO ("Block until element is waiting for a clock notification\n");
119    ///   gst_test_clock_wait_for_next_pending_id (test_clock, &pending_id);
120    ///   GST_INFO ("Advance to the requested time of the clock notification\n");
121    ///   gst_test_clock_advance_time (test_clock, latency);
122    ///   GST_INFO ("Release the next blocking wait and make sure it is the one from element\n");
123    ///   processed_id = gst_test_clock_process_next_clock_id (test_clock);
124    ///   g_assert (processed_id == pending_id);
125    ///   g_assert_cmpint (GST_CLOCK_ENTRY_STATUS (processed_id), ==, GST_CLOCK_OK);
126    ///   gst_clock_id_unref (pending_id);
127    ///   gst_clock_id_unref (processed_id);
128    ///
129    ///   GST_INFO ("Validate that element produced an output buffer and check its timestamp\n");
130    ///   g_assert_cmpint (get_number_of_output_buffer (...), ==, 1);
131    ///   buf = get_buffer_pushed_by_element (element, ...);
132    ///   g_assert_cmpint (GST_BUFFER_TIMESTAMP (buf), ==, latency);
133    ///   gst_buffer_unref (buf);
134    ///   GST_INFO ("Check that element does not wait for any clock notification\n");
135    ///   g_assert (!gst_test_clock_peek_next_pending_id (test_clock, NULL));
136    ///
137    ///   GST_INFO ("Set time, create and push the second buffer\n");
138    ///   gst_test_clock_advance_time (test_clock, 10 * GST_SECOND);
139    ///   buf = create_test_buffer (gst_clock_get_time (clock), ...);
140    ///   gst_assert_cmpint (gst_pad_push (srcpad, buf), ==, GST_FLOW_OK);
141    ///
142    ///   GST_INFO ("Block until element is waiting for a new clock notification\n");
143    ///   (gst_test_clock_wait_for_next_pending_id (test_clock, &pending_id);
144    ///   GST_INFO ("Advance past 7ms beyond the requested time of the clock notification\n");
145    ///   gst_test_clock_advance_time (test_clock, latency + 7 * GST_MSECOND);
146    ///   GST_INFO ("Release the next blocking wait and make sure it is the one from element\n");
147    ///   processed_id = gst_test_clock_process_next_clock_id (test_clock);
148    ///   g_assert (processed_id == pending_id);
149    ///   g_assert_cmpint (GST_CLOCK_ENTRY_STATUS (processed_id), ==, GST_CLOCK_OK);
150    ///   gst_clock_id_unref (pending_id);
151    ///   gst_clock_id_unref (processed_id);
152    ///
153    ///   GST_INFO ("Validate that element produced an output buffer and check its timestamp\n");
154    ///   g_assert_cmpint (get_number_of_output_buffer (...), ==, 1);
155    ///   buf = get_buffer_pushed_by_element (element, ...);
156    ///   g_assert_cmpint (GST_BUFFER_TIMESTAMP (buf), ==,
157    ///       10 * GST_SECOND + latency + 7 * GST_MSECOND);
158    ///   gst_buffer_unref (buf);
159    ///   GST_INFO ("Check that element does not wait for any clock notification\n");
160    ///   g_assert (!gst_test_clock_peek_next_pending_id (test_clock, NULL));
161    ///   ...
162    /// ```
163    ///
164    /// Since [`TestClock`][crate::TestClock] is only supposed to be used in unit tests it calls
165    /// `g_assert()`, `g_assert_cmpint()` or `g_assert_cmpuint()` to validate all function
166    /// arguments. This will highlight any issues with the unit test code itself.
167    ///
168    /// ## Properties
169    ///
170    ///
171    /// #### `clock-type`
172    ///  Readable | Writeable
173    ///
174    ///
175    /// #### `start-time`
176    ///  When a [`TestClock`][crate::TestClock] is constructed it will have a certain start time set.
177    /// If the clock was created using [`TestClock::with_start_time()`][crate::TestClock::with_start_time()] then
178    /// this property contains the value of the `start_time` argument. If
179    /// [`TestClock::new()`][crate::TestClock::new()] was called the clock started at time zero, and thus
180    /// this property contains the value 0.
181    ///
182    /// Readable | Writeable | Construct Only
183    /// <details><summary><h4>Clock</h4></summary>
184    ///
185    ///
186    /// #### `timeout`
187    ///  Readable | Writeable
188    ///
189    ///
190    /// #### `window-size`
191    ///  Readable | Writeable
192    ///
193    ///
194    /// #### `window-threshold`
195    ///  Readable | Writeable
196    /// </details>
197    /// <details><summary><h4>Object</h4></summary>
198    ///
199    ///
200    /// #### `name`
201    ///  Readable | Writeable | Construct
202    ///
203    ///
204    /// #### `parent`
205    ///  The parent of the object. Please note, that when changing the 'parent'
206    /// property, we don't emit [`notify`][struct@crate::glib::Object#notify] and [`deep-notify`][struct@crate::gst::Object#deep-notify]
207    /// signals due to locking issues. In some cases one can use
208    /// [`element-added`][struct@crate::gst::Bin#element-added] or [`element-removed`][struct@crate::gst::Bin#element-removed] signals on the parent to
209    /// achieve a similar effect.
210    ///
211    /// Readable | Writeable
212    /// </details>
213    ///
214    /// # Implements
215    ///
216    /// [`trait@gst::prelude::ClockExt`], [`trait@gst::prelude::ObjectExt`], [`trait@glib::ObjectExt`]
217    #[doc(alias = "GstTestClock")]
218    pub struct TestClock(Object<ffi::GstTestClock, ffi::GstTestClockClass>) @extends gst::Clock, gst::Object;
219
220    match fn {
221        type_ => || ffi::gst_test_clock_get_type(),
222    }
223}
224
225impl TestClock {
226    /// Creates a new test clock with its time set to zero.
227    ///
228    /// MT safe.
229    ///
230    /// # Returns
231    ///
232    /// a [`TestClock`][crate::TestClock] cast to [`gst::Clock`][crate::gst::Clock].
233    #[doc(alias = "gst_test_clock_new")]
234    pub fn new() -> TestClock {
235        assert_initialized_main_thread!();
236        unsafe { gst::Clock::from_glib_full(ffi::gst_test_clock_new()).unsafe_cast() }
237    }
238
239    /// Creates a new test clock with its time set to the specified time.
240    ///
241    /// MT safe.
242    /// ## `start_time`
243    /// a `GstClockTime` set to the desired start time of the clock.
244    ///
245    /// # Returns
246    ///
247    /// a [`TestClock`][crate::TestClock] cast to [`gst::Clock`][crate::gst::Clock].
248    #[doc(alias = "gst_test_clock_new_with_start_time")]
249    #[doc(alias = "new_with_start_time")]
250    pub fn with_start_time(start_time: gst::ClockTime) -> TestClock {
251        assert_initialized_main_thread!();
252        unsafe {
253            gst::Clock::from_glib_full(ffi::gst_test_clock_new_with_start_time(
254                start_time.into_glib(),
255            ))
256            .unsafe_cast()
257        }
258    }
259
260    /// Advances the time of the `self` by the amount given by `delta`. The
261    /// time of `self` is monotonically increasing, therefore providing a
262    /// `delta` which is negative or zero is a programming error.
263    ///
264    /// MT safe.
265    /// ## `delta`
266    /// a positive `GstClockTimeDiff` to be added to the time of the clock
267    #[doc(alias = "gst_test_clock_advance_time")]
268    pub fn advance_time(&self, delta: gst::ClockTimeDiff) {
269        unsafe {
270            ffi::gst_test_clock_advance_time(self.to_glib_none().0, delta);
271        }
272    }
273
274    /// A "crank" consists of three steps:
275    /// 1: Wait for a `GstClockID` to be registered with the [`TestClock`][crate::TestClock].
276    /// 2: Advance the [`TestClock`][crate::TestClock] to the time the `GstClockID` is waiting, unless
277    ///  the clock time is already passed the clock id (Since: 1.18).
278    /// 3: Release the `GstClockID` wait.
279    /// A "crank" can be though of as the notion of
280    /// manually driving the clock forward to its next logical step.
281    ///
282    /// # Returns
283    ///
284    /// [`true`] if the crank was successful, [`false`] otherwise.
285    ///
286    /// MT safe.
287    #[doc(alias = "gst_test_clock_crank")]
288    pub fn crank(&self) -> bool {
289        unsafe { from_glib(ffi::gst_test_clock_crank(self.to_glib_none().0)) }
290    }
291
292    /// Retrieve the requested time for the next pending clock notification.
293    ///
294    /// MT safe.
295    ///
296    /// # Returns
297    ///
298    /// a `GstClockTime` set to the time of the next pending clock
299    /// notification. If no clock notifications have been requested
300    /// `GST_CLOCK_TIME_NONE` will be returned.
301    #[doc(alias = "gst_test_clock_get_next_entry_time")]
302    #[doc(alias = "get_next_entry_time")]
303    pub fn next_entry_time(&self) -> Option<gst::ClockTime> {
304        unsafe {
305            from_glib(ffi::gst_test_clock_get_next_entry_time(
306                self.to_glib_none().0,
307            ))
308        }
309    }
310
311    /// Determine the number of pending clock notifications that have been
312    /// requested from the `self`.
313    ///
314    /// MT safe.
315    ///
316    /// # Returns
317    ///
318    /// the number of pending clock notifications.
319    #[doc(alias = "gst_test_clock_peek_id_count")]
320    pub fn peek_id_count(&self) -> u32 {
321        unsafe { ffi::gst_test_clock_peek_id_count(self.to_glib_none().0) }
322    }
323
324    /// Sets the time of `self` to the time given by `new_time`. The time of
325    /// `self` is monotonically increasing, therefore providing a `new_time`
326    /// which is earlier or equal to the time of the clock as given by
327    /// [`ClockExtManual::time()`][crate::gst::prelude::ClockExtManual::time()] is a programming error.
328    ///
329    /// MT safe.
330    /// ## `new_time`
331    /// a `GstClockTime` later than that returned by [`ClockExtManual::time()`][crate::gst::prelude::ClockExtManual::time()]
332    #[doc(alias = "gst_test_clock_set_time")]
333    pub fn set_time(&self, new_time: gst::ClockTime) {
334        unsafe {
335            ffi::gst_test_clock_set_time(self.to_glib_none().0, new_time.into_glib());
336        }
337    }
338
339    /// Blocks until at least `count` clock notifications have been requested from
340    /// `self`. There is no timeout for this wait, see the main description of
341    /// [`TestClock`][crate::TestClock].
342    ///
343    /// # Deprecated
344    ///
345    /// use [`wait_for_multiple_pending_ids()`][Self::wait_for_multiple_pending_ids()] instead.
346    /// ## `count`
347    /// the number of pending clock notifications to wait for
348    #[doc(alias = "gst_test_clock_wait_for_pending_id_count")]
349    pub fn wait_for_pending_id_count(&self, count: u32) {
350        unsafe {
351            ffi::gst_test_clock_wait_for_pending_id_count(self.to_glib_none().0, count);
352        }
353    }
354
355    #[doc(alias = "clock-type")]
356    pub fn clock_type(&self) -> gst::ClockType {
357        ObjectExt::property(self, "clock-type")
358    }
359
360    #[doc(alias = "clock-type")]
361    pub fn set_clock_type(&self, clock_type: gst::ClockType) {
362        ObjectExt::set_property(self, "clock-type", clock_type)
363    }
364
365    /// When a [`TestClock`][crate::TestClock] is constructed it will have a certain start time set.
366    /// If the clock was created using [`with_start_time()`][Self::with_start_time()] then
367    /// this property contains the value of the `start_time` argument. If
368    /// [`new()`][Self::new()] was called the clock started at time zero, and thus
369    /// this property contains the value 0.
370    #[doc(alias = "start-time")]
371    pub fn start_time(&self) -> u64 {
372        ObjectExt::property(self, "start-time")
373    }
374
375    //#[doc(alias = "gst_test_clock_id_list_get_latest_time")]
376    //pub fn id_list_get_latest_time(pending_list: /*Unimplemented*/&[&gst::ClockID]) -> Option<gst::ClockTime> {
377    //    unsafe { TODO: call ffi:gst_test_clock_id_list_get_latest_time() }
378    //}
379
380    #[doc(alias = "clock-type")]
381    pub fn connect_clock_type_notify<F: Fn(&Self) + Send + Sync + 'static>(
382        &self,
383        f: F,
384    ) -> SignalHandlerId {
385        unsafe extern "C" fn notify_clock_type_trampoline<
386            F: Fn(&TestClock) + Send + Sync + 'static,
387        >(
388            this: *mut ffi::GstTestClock,
389            _param_spec: glib::ffi::gpointer,
390            f: glib::ffi::gpointer,
391        ) {
392            let f: &F = &*(f as *const F);
393            f(&from_glib_borrow(this))
394        }
395        unsafe {
396            let f: Box_<F> = Box_::new(f);
397            connect_raw(
398                self.as_ptr() as *mut _,
399                c"notify::clock-type".as_ptr() as *const _,
400                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
401                    notify_clock_type_trampoline::<F> as *const (),
402                )),
403                Box_::into_raw(f),
404            )
405        }
406    }
407}
408
409impl Default for TestClock {
410    fn default() -> Self {
411        Self::new()
412    }
413}
414
415unsafe impl Send for TestClock {}
416unsafe impl Sync for TestClock {}