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 {}