Skip to main content

cidre/cm/
sync.rs

1use crate::{arc, cf, cm, define_cf_type, os};
2
3#[cfg(feature = "dispatch")]
4use crate::dispatch;
5
6define_cf_type!(
7    /// A timing source object.
8    ///
9    /// A clock represents a source of time information: generally, a piece of hardware that measures the passage of time.
10    /// One example of a clock is the host time clock, accessible via cm::Clock::host_time_clock().
11    /// It measures time using the CPU system clock, which on Mac OS X is mach_absolute_time().
12    /// Every audio device can also be considered a clock since the audio samples that it outputs or inputs each have a
13    /// defined duration (eg, 1/48000 of a second for 48 kHz audio).
14    ///
15    /// cm::Clocks are read-only: they cannot be stopped or started, and the current time cannot be set.
16    /// A CMClock has one primary function, cm::Clock::get_time, which tells what time it is now.
17    /// Additionally, the cm::Sync infrastructure monitors relative drift between cm::Clocks.
18    #[doc(alias = "CMClock")]
19    #[doc(alias = "CMClockRef")]
20    Clock(ClockOrTimebase)
21);
22
23define_cf_type!(
24    /// Models a timeline under application control.
25    ///
26    /// A timebase represents a timeline that clients can control by setting the rate and time.
27    /// Each timebase has either a source clock or a source timebase (previously referred to as a master clock or master timebase).
28    /// The rate of the timebase is expressed relative to its source.
29    /// When a timebase has rate 0.0, its time is fixed and does not change as its source's time changes.
30    /// When a timebase has rate 1.0, its time increases one second as its source's time increases by one second.
31    /// When a timebase has rate 2.0, its time increases two seconds as its source's time increases by one second.
32    /// When a timebase has rate -1.0, its time decreases one second as its source's time increases by one second.
33    ///
34    /// If a timebase has a source timebase, the source timebase's rate is a factor in determining the timebase's effective rate.
35    /// In fact, a timebase's effective rate is defined as the product of its rate, its source timebase's rate,
36    /// its source timebase's source timebase's rate, and so on up to the ultimate source clock.  This is the rate at which
37    /// the timebase's time changes relative to the ultimate source clock.
38    #[doc(alias = "CMTimebase")]
39    #[doc(alias = "CMTimebaseRef")]
40    Timebase(ClockOrTimebase)
41);
42
43define_cf_type!(
44    #[doc(alias = "CMClockOrTimebase")]
45    #[doc(alias = "CMClockOrTimebaseRef")]
46    ClockOrTimebase(cf::Type)
47);
48
49unsafe impl Send for Clock {}
50unsafe impl Send for Timebase {}
51unsafe impl Send for ClockOrTimebase {}
52
53impl Clock {
54    #[doc(alias = "CMClockGetTypeID")]
55    pub fn get_type_id() -> cf::TypeId {
56        unsafe { CMClockGetTypeID() }
57    }
58
59    /// Returns a reference to the singleton clock logically identified with host time.
60    #[inline]
61    #[doc(alias = "CMClockGetHostTimeClock")]
62    pub fn host_time_clock() -> &'static Clock {
63        unsafe { CMClockGetHostTimeClock() }
64    }
65
66    #[doc(alias = "CMClockGetTime")]
67    #[inline]
68    pub fn time(&self) -> cm::Time {
69        unsafe { CMClockGetTime(self) }
70    }
71
72    /// Converts a host time from CMTime to the host time's native units.
73    ///
74    /// This function performs a scale conversion, not a clock conversion.
75    /// It can be more accurate than CMTimeConvertScale because the system units may
76    /// have a non-integer timescale.
77    /// On Mac OS X, this function converts to the units of mach_absolute_time.
78    #[doc(alias = "CMClockConvertHostTimeToSystemUnits")]
79    #[inline]
80    pub fn convert_host_time_to_sys_units(host_time: cm::Time) -> u64 {
81        unsafe { CMClockConvertHostTimeToSystemUnits(host_time) }
82    }
83
84    /// Converts a host time from native units to cm::Time.
85    #[doc(alias = "CMClockMakeHostTimeFromSystemUnits")]
86    #[inline]
87    pub fn make_host_time_from_sys_units(host_time: u64) -> cm::Time {
88        unsafe { CMClockMakeHostTimeFromSystemUnits(host_time) }
89    }
90
91    #[doc(alias = "CMClockGetAnchorTime")]
92    #[inline]
93    pub fn anchor_time(
94        &self,
95        clock_time_out: &mut cm::Time,
96        ref_clock_time_out: &mut cm::Time,
97    ) -> os::Result {
98        unsafe { CMClockGetAnchorTime(self, clock_time_out, ref_clock_time_out).result() }
99    }
100
101    /// Indicates whether it is possible for two clocks to drift relative to each other.
102    #[doc(alias = "CMClockMightDrift")]
103    #[inline]
104    pub fn might_dirft(&self, other: &Clock) -> bool {
105        unsafe { CMClockMightDrift(self, other) }
106    }
107
108    /// Makes the clock stop functioning.
109    ///
110    /// After invalidation, the clock will return errors from all APIs.
111    /// This should only be called by the "owner" of the clock, who knows (for example)
112    /// that some piece of hardware has gone away, and the clock will no longer work (and might even crash).
113    #[doc(alias = "CMClockInvalidate")]
114    #[inline]
115    pub fn invalidate(&mut self) {
116        unsafe { CMClockInvalidate(self) }
117    }
118}
119
120/// cm::Clock error codes
121pub mod clock_err {
122    use crate::os::Error;
123
124    #[doc(alias = "kCMClockError_MissingRequiredParameter")]
125    pub const MISSING_REQUIRED_PARAM: Error = Error::new_unchecked(-12745);
126
127    #[doc(alias = "kCMClockError_InvalidParameter")]
128    pub const INVALID_PARAM: Error = Error::new_unchecked(-12746);
129
130    #[doc(alias = "kCMClockError_AllocationFailed")]
131    pub const ALLOC_FAILED: Error = Error::new_unchecked(-12747);
132
133    #[doc(alias = "kCMClockError_UnsupportedOperation")]
134    pub const UNSUPPORTED_OP: Error = Error::new_unchecked(-12756);
135}
136
137/// cm::Timebase error codes
138pub mod timebase_err {
139    use crate::os::Error;
140
141    #[doc(alias = "kCMTimebaseError_MissingRequiredParameter")]
142    pub const MISSING_REQUIRED_PARAM: Error = Error::new_unchecked(-12748);
143
144    #[doc(alias = "kCMTimebaseError_InvalidParameter")]
145    pub const INVALID_PARAM: Error = Error::new_unchecked(-12749);
146
147    #[doc(alias = "kCMTimebaseError_AllocationFailed")]
148    pub const ALLOC_FAILED: Error = Error::new_unchecked(-12750);
149
150    #[doc(alias = "kCMTimebaseError_TimerIntervalTooShort")]
151    pub const TIMER_INTERVAL_TOO_SHORT: Error = Error::new_unchecked(-12751);
152
153    #[doc(alias = "kCMTimebaseError_ReadOnly")]
154    pub const READ_ONLY: Error = Error::new_unchecked(-12757);
155}
156
157pub mod sync_err {
158    use crate::os::Error;
159
160    #[doc(alias = "kCMSyncError_MissingRequiredParameter")]
161    pub const MISSING_REQUIRED_PARAMETER: Error = Error::new_unchecked(-12752);
162
163    #[doc(alias = "kCMSyncError_InvalidParameter")]
164    pub const INVALID_PARAMETER: Error = Error::new_unchecked(-12753);
165
166    #[doc(alias = "kCMSyncError_AllocationFailed")]
167    pub const ALLOC_FAILED: Error = Error::new_unchecked(-12754);
168
169    #[doc(alias = "kCMSyncError_RateMustBeNonZero")]
170    pub const RATE_MUST_BE_NON_ZERO: Error = Error::new_unchecked(-12755);
171}
172
173unsafe extern "C-unwind" {
174    fn CMClockGetTypeID() -> cf::TypeId;
175    fn CMClockGetHostTimeClock() -> &'static Clock;
176
177    fn CMClockGetTime(clock: &Clock) -> cm::Time;
178    fn CMClockGetAnchorTime(
179        clock: &Clock,
180        clock_time_out: &mut cm::Time,
181        ref_clock_time_out: &mut cm::Time,
182    ) -> os::Status;
183    fn CMClockMightDrift(clock: &Clock, other_clock: &Clock) -> bool;
184    fn CMClockInvalidate(clock: &mut Clock);
185    fn CMClockConvertHostTimeToSystemUnits(host_time: cm::Time) -> u64;
186    fn CMClockMakeHostTimeFromSystemUnits(host_time: u64) -> cm::Time;
187}
188
189impl Timebase {
190    #[doc(alias = "CMTimebaseGetTypeID")]
191    pub fn get_type_id() -> cf::TypeId {
192        unsafe { CMTimebaseGetTypeID() }
193    }
194
195    #[doc(alias = "CMTimebaseCreateWithSourceClock")]
196    pub fn with_src_clock_in(
197        src_clock: &cm::Clock,
198        allocator: Option<&cf::Allocator>,
199    ) -> os::Result<arc::R<Self>> {
200        unsafe {
201            os::result_unchecked(|res| CMTimebaseCreateWithSourceClock(allocator, src_clock, res))
202        }
203    }
204
205    /// Creates a timebase driven by the given clock.
206    ///
207    /// The timebase will initially have rate zero and time zero.
208    /// Pass cm::Clock::host_time_clock() for source_clock to have the host time clock drive
209    /// this timebase.
210    #[doc(alias = "CMTimebaseCreateWithSourceClock")]
211    pub fn with_src_clock(src_clock: &cm::Clock) -> os::Result<arc::R<Self>> {
212        Self::with_src_clock_in(src_clock, None)
213    }
214
215    #[doc(alias = "CMTimebaseCreateWithSourceTimebase")]
216    pub fn with_src_timebase_in(
217        src_timebase: &cm::Timebase,
218        allocator: Option<&cf::Allocator>,
219    ) -> os::Result<arc::R<Self>> {
220        unsafe {
221            os::result_unchecked(|res| {
222                CMTimebaseCreateWithSourceTimebase(allocator, src_timebase, res)
223            })
224        }
225    }
226
227    /// Creates a timebase driven by the given source timebase.
228    ///
229    /// The timebase will initially have rate zero and time zero.
230    #[doc(alias = "CMTimebaseCreateWithSourceTimebase")]
231    #[inline]
232    pub fn with_src_timebase(src_timebase: &cm::Timebase) -> os::Result<arc::R<Self>> {
233        Self::with_src_timebase_in(src_timebase, None)
234    }
235
236    /// Returns the immediate source timebase of a timebase.
237    ///
238    /// Returns None if the timebase actually has a source clock instead of a source timebase.
239    #[doc(alias = "CMTimebaseCopySourceTimebase")]
240    #[inline]
241    pub fn src_timebase(&self) -> Option<arc::R<cm::Timebase>> {
242        unsafe { CMTimebaseCopySourceTimebase(self) }
243    }
244
245    /// Returns the immediate source clock of a timebase.
246    ///
247    /// Returns None if the timebase actually has a source timebase instead of a source clock.
248    #[doc(alias = "CMTimebaseCopySourceClock")]
249    #[inline]
250    pub fn src_clock(&self) -> Option<arc::R<cm::Clock>> {
251        unsafe { CMTimebaseCopySourceClock(self) }
252    }
253
254    /// Returns the immediate source (either timebase or clock) of a timebase.
255    #[doc(alias = "CMTimebaseCopySource")]
256    #[inline]
257    pub fn src(&self) -> arc::R<cm::ClockOrTimebase> {
258        unsafe { CMTimebaseCopySource(self) }
259    }
260
261    /// Returns the source clock that is the source of all of a timebase's source timebases.
262    #[doc(alias = "CMTimebaseCopyUltimateSourceClock")]
263    #[inline]
264    pub fn ultimate_src_clock(&self) -> arc::R<cm::Clock> {
265        unsafe { CMTimebaseCopyUltimateSourceClock(self) }
266    }
267
268    /// Sets the source clock of a timebase.
269    ///
270    /// The timebase will stop receiving timing information from its current source clock or source
271    /// timebase, and will begin receiving timing information from the new source clock.  Prior to
272    /// the change a cm::Timebase::notification_src_will_change will be posted.  When
273    /// the change has completed, a cm::Timebase::notification_src_did_change notification
274    /// will be posted.
275    #[doc(alias = "CMTimebaseSetSourceClock")]
276    #[inline]
277    pub fn set_src_clock(&mut self, val: &cm::Clock) -> os::Result {
278        unsafe { CMTimebaseSetSourceClock(self, val).result() }
279    }
280
281    /// Sets the source timebase of a timebase.
282    ///
283    /// The timebase will stop receiving timing information from its current source clock or source
284    /// timebase, and will begin receiving timing information from the new source timebase.  Prior to
285    /// the change a cm::Timebase::notification_src_will_change will be posted.  When
286    /// the change has completed, a cm::Timebase::notification_src_did_change notification
287    /// will be posted.
288    #[doc(alias = "CMTimebaseSetSourceTimebase")]
289    #[inline]
290    pub fn set_src_timebase(&mut self, val: &cm::Timebase) -> os::Result {
291        unsafe { CMTimebaseSetSourceTimebase(self, val).result() }
292    }
293
294    #[doc(alias = "kCMTimebaseNotification_SourceWillChange")]
295    #[inline]
296    pub fn notification_src_will_change() -> &'static cf::NotificationName {
297        unsafe { kCMTimebaseNotification_SourceWillChange }
298    }
299
300    #[doc(alias = "kCMTimebaseNotification_SourceDidChange")]
301    #[inline]
302    pub fn notification_src_did_change() -> &'static cf::NotificationName {
303        unsafe { kCMTimebaseNotification_SourceDidChange }
304    }
305
306    #[doc(alias = "kCMTimebaseNotification_EffectiveRateChanged")]
307    #[inline]
308    pub fn notification_effective_rate_changed() -> &'static cf::NotificationName {
309        unsafe { kCMTimebaseNotification_EffectiveRateChanged }
310    }
311
312    #[doc(alias = "kCMTimebaseNotification_TimeJumped")]
313    #[inline]
314    pub fn notification_time_jumped() -> &'static cf::NotificationName {
315        unsafe { kCMTimebaseNotification_TimeJumped }
316    }
317
318    #[doc(alias = "kCMTimebaseNotificationKey_EventTime")]
319    #[inline]
320    pub fn notification_key_event_time() -> &'static cf::String {
321        unsafe { kCMTimebaseNotificationKey_EventTime }
322    }
323
324    /// Retrieves the current time from a timebase.
325    #[doc(alias = "CMTimebaseGetTime")]
326    #[inline]
327    pub fn time(&self) -> cm::Time {
328        unsafe { CMTimebaseGetTime(self) }
329    }
330
331    /// Retrieves the current time from a timebase in the specified timescale.
332    #[doc(alias = "CMTimebaseGetTimeWithTimeScale")]
333    #[inline]
334    pub fn time_with_scale(
335        &self,
336        timescale: cm::TimeScale,
337        method: cm::TimeRoundingMethod,
338    ) -> cm::Time {
339        unsafe { CMTimebaseGetTimeWithTimeScale(self, timescale, method) }
340    }
341
342    /// Sets the current time of a timebase.  
343    #[doc(alias = "CMTimebaseSetTime")]
344    #[inline]
345    pub fn set_time(&mut self, val: cm::Time) -> os::Result {
346        unsafe { CMTimebaseSetTime(self, val).result() }
347    }
348
349    /// Sets the time of a timebase at a particular source time.
350    ///
351    /// cm::Timebase::time's results will be interpolated from that anchor time.
352    #[doc(alias = "CMTimebaseSetAnchorTime")]
353    #[inline]
354    pub fn set_achor_time(
355        &mut self,
356        timebase_time: cm::Time,
357        immediate_src_time: cm::Time,
358    ) -> os::Result {
359        unsafe { CMTimebaseSetAnchorTime(self, timebase_time, immediate_src_time).result() }
360    }
361
362    /// Retrieves the current rate of a timebase.  
363    ///
364    /// This is the rate relative to its immediate source clock or timebase.  
365    /// For example, if a timebase is running at twice the rate of its source, its rate is 2.0.
366    #[doc(alias = "CMTimebaseGetRate")]
367    #[inline]
368    pub fn rate(&self) -> f64 {
369        unsafe { CMTimebaseGetRate(self) }
370    }
371
372    /// Retrieves the current time and rate of a timebase.
373    ///
374    /// You can use this function to take a consistent snapshot of the two values,
375    /// avoiding possible inconsistencies due to external changes between retrieval of time and rate.
376    #[doc(alias = "CMTimebaseGetTimeAndRate")]
377    #[inline]
378    pub fn time_and_rate(&self, time_out: &mut cm::Time, rate_out: &mut f64) -> os::Result {
379        unsafe { CMTimebaseGetTimeAndRate(self, time_out, rate_out).result() }
380    }
381
382    /// Sets the rate of a timebase.
383    #[doc(alias = "CMTimebaseSetRate")]
384    #[inline]
385    pub fn set_rate(&mut self, val: f64) -> os::Result {
386        unsafe { CMTimebaseSetRate(self, val).result() }
387    }
388
389    /// Sets the time of a timebase at a particular source time, and changes the rate at exactly that time.
390    #[doc(alias = "CMTimebaseSetRateAndAnchorTime")]
391    #[inline]
392    pub fn set_rate_and_anchor_time(
393        &mut self,
394        rate: f64,
395        timebase_time: cm::Time,
396        immediate_src_time: cm::Time,
397    ) -> os::Result {
398        unsafe {
399            CMTimebaseSetRateAndAnchorTime(self, rate, timebase_time, immediate_src_time).result()
400        }
401    }
402
403    /// Gets the effective rate of a timebase (which combines its rate with the rates of all its source timebases).
404    #[doc(alias = "CMTimebaseGetEffectiveRate")]
405    #[inline]
406    pub fn effective_rate(&self) -> f64 {
407        unsafe { CMTimebaseGetEffectiveRate(self) }
408    }
409
410    /// Adds the timer to the list of timers managed by the timebase.
411    ///
412    /// The timer must be a repeating run loop timer (with a very long interval at
413    /// least as long as cm::Timebase::VERY_LONG_CF_TIME_INTERVAL), attached to a runloop.  
414    /// The timebase will retain the timer, and will maintain its "NextFireDate"
415    /// according to the cm::Time set using CMTimebaseSetTimerNextFireTime.
416    /// Until the first call to CMTimebaseSetTimerNextFireTime, the "NextFireDate"
417    /// will be set far, far in the future. The runloop that timer is attached to must be
418    /// passed in and the timebase will retain that runloop. The retained runloop will be
419    /// used to call cf::RunLoop::wake_up() any time the timebase modifies the timer's fire date.
420    #[doc(alias = "CMTimebaseAddTimer")]
421    #[inline]
422    pub fn add_timer(&mut self, timer: &cf::RunLoopTimer, run_loop: &cf::RunLoop) -> os::Result {
423        unsafe { CMTimebaseAddTimer(self, timer, run_loop).result() }
424    }
425
426    /// quite a while
427    pub const VERY_LONG_CF_TIME_INTERVAL: cf::TimeInterval = 256.0 * 365.0 * 24.0 * 60.0 * 60.0;
428
429    /// quite a while from 2001
430    pub const FAR_FUTURE_CF_ABS_TIME: cf::AbsTime = Self::VERY_LONG_CF_TIME_INTERVAL;
431
432    /// Removes the timer from the list of timers managed by the timebase.
433    ///
434    /// The timebase will no longer maintain the timer's "NextFireDate".
435    /// If the timer is invalidated, the timebase will eventually remove it
436    /// from its list and release it even if this function is not called.
437    #[doc(alias = "CMTimebaseRemoveTimer")]
438    #[inline]
439    pub fn remove_timer(&mut self, timer: &cf::RunLoopTimer) -> os::Result {
440        unsafe { CMTimebaseRemoveTimer(self, timer).result() }
441    }
442
443    /// Sets the cm::Time on the timebase's timeline at which the timer should next be fired.
444    ///
445    /// The timer must be on the list of timers managed by the timebase.
446    /// The timebase will continue to update the timer's "NextFireDate" according to time jumps
447    /// and effective rate changes.
448    /// If fireTime is not numeric, or if the timebase is not moving, the "NextFireDate"
449    /// will be set to a date far, far in the future.
450    ///
451    /// IMPORTANT NOTE: Due to the way that cf::RunLoopTimers are implemented, if a timer passes
452    /// through a state in which it is due to fire, it may fire even if its rescheduled before
453    /// the runloop runs again.  Clients should take care to avoid temporarily scheduling timers
454    /// in the past.  For example, set the timebase's rate or time before you set the timer's
455    /// next fire time, if you are doing both at once.  (If setting the timebase's rate or time
456    /// might put the timer's fire time in the past, you may need to set the fire time to
457    /// cm::Time::invalid() across the timebase change.)
458    #[doc(alias = "CMTimebaseSetTimerNextFireTime")]
459    #[inline]
460    pub fn set_timer_next_fire_time(
461        &self,
462        timer: &mut cf::RunLoopTimer,
463        fire_time: cm::Time,
464    ) -> os::Result {
465        unsafe { CMTimebaseSetTimerNextFireTime(self, timer, fire_time, 0).result() }
466    }
467
468    /// Sets the timer to fire immediately once, overriding any previous cm::Timebase::set_timer_next_fire_time call.
469    ///
470    ///
471    #[doc(alias = "CMTimebaseSetTimerToFireImmediately")]
472    #[inline]
473    pub fn set_timer_to_fire_immediately(&self, timer: &mut cf::RunLoopTimer) -> os::Result {
474        unsafe { CMTimebaseSetTimerToFireImmediately(self, timer).result() }
475    }
476
477    /// Adds the timer dispatch source to the list of timers managed by the timebase.
478    ///
479    ///
480    #[doc(alias = "CMTimebaseAddTimerDispatchSource")]
481    #[inline]
482    #[cfg(feature = "dispatch")]
483    pub fn add_timer_dispatch_src(&mut self, timer_src: &dispatch::TimerSrc) -> os::Result {
484        unsafe { CMTimebaseAddTimerDispatchSource(self, timer_src).result() }
485    }
486
487    /// Removes the timer dispatch source from the list of timers managed by the timebase.
488    ///
489    /// The timebase will no longer maintain the timer source's start time.
490    /// If the timer source is cancelled, the timebase will eventually remove it
491    /// from its list and release it even if this function is not called.
492    #[doc(alias = "CMTimebaseRemoveTimerDispatchSource")]
493    #[inline]
494    #[cfg(feature = "dispatch")]
495    pub fn remove_timer_dispatch_src(&mut self, timer_src: &dispatch::TimerSrc) -> os::Result {
496        unsafe { CMTimebaseRemoveTimerDispatchSource(self, timer_src).result() }
497    }
498
499    /// Sets the cm::Time on the timebase's timeline at which the timer dispatch source should next be fired.
500    ///
501    /// The timer source must be on the list of timers managed by the timebase.
502    /// The timebase will continue to update the timer dispatch source's start time
503    /// according to time jumps and effective rate changes.
504    /// If fireTime is not numeric, or if the timebase is not moving, the start time
505    /// will be set to DISPATCH_TIME_FOREVER.
506    ///
507    /// IMPORTANT NOTE: Due to the way that timer dispatch sources are implemented, if a timer passes
508    /// through a state in which it is due to fire, it may fire even if its rescheduled before
509    /// the event handler is run.  Clients should take care to avoid temporarily scheduling timers
510    /// in the past.  For example, set the timebase's rate or time before you set the timer's
511    /// next fire time, if you are doing both at once.  (If setting the timebase's rate or time
512    /// might put the timer's fire time in the past, you may need to set the fire time to
513    /// kCMTimeInvalid across the timebase change.)
514    #[doc(alias = "CMTimebaseSetTimerDispatchSourceNextFireTime")]
515    #[inline]
516    #[cfg(feature = "dispatch")]
517    pub fn set_timer_dispatch_src_next_fire_time(
518        &mut self,
519        timer_src: &dispatch::TimerSrc,
520        fire_time: cm::Time,
521    ) -> os::Result {
522        unsafe {
523            CMTimebaseSetTimerDispatchSourceNextFireTime(self, timer_src, fire_time, 0).result()
524        }
525    }
526
527    /// Sets the timer dispatch source to fire immediately once, overriding any previous
528    /// cm::Timebase::set_timer_dispatch_src_next_fire_time call.
529    #[doc(alias = "CMTimebaseSetTimerDispatchSourceToFireImmediately")]
530    #[inline]
531    #[cfg(feature = "dispatch")]
532    pub fn set_timer_dispatch_src_to_fire_immediately(
533        &mut self,
534        timer_src: &dispatch::TimerSrc,
535    ) -> os::Result {
536        unsafe { CMTimebaseSetTimerDispatchSourceToFireImmediately(self, timer_src).result() }
537    }
538
539    /// Requests that the timebase wait until it is not posting any notifications.
540    #[doc(alias = "CMTimebaseNotificationBarrier")]
541    #[inline]
542    pub fn notification_barrier(&self) -> os::Result {
543        unsafe { CMTimebaseNotificationBarrier(self).result() }
544    }
545}
546
547unsafe extern "C-unwind" {
548    fn CMTimebaseGetTypeID() -> cf::TypeId;
549
550    fn CMTimebaseCreateWithSourceClock(
551        allocator: Option<&cf::Allocator>,
552        source_clock: &cm::Clock,
553        timebase_out: *mut Option<arc::R<cm::Timebase>>,
554    ) -> os::Status;
555
556    fn CMTimebaseCreateWithSourceTimebase(
557        allocator: Option<&cf::Allocator>,
558        source_timebase: &cm::Timebase,
559        timebase_out: *mut Option<arc::R<cm::Timebase>>,
560    ) -> os::Status;
561
562    fn CMTimebaseCopySourceTimebase(timebase: &cm::Timebase) -> Option<arc::R<cm::Timebase>>;
563
564    fn CMTimebaseCopySourceClock(timebase: &cm::Timebase) -> Option<arc::R<cm::Clock>>;
565
566    fn CMTimebaseCopySource(timebase: &cm::Timebase) -> arc::R<cm::ClockOrTimebase>;
567
568    fn CMTimebaseCopyUltimateSourceClock(timebase: &cm::Timebase) -> arc::R<cm::Clock>;
569
570    fn CMTimebaseSetSourceClock(
571        timebase: &mut cm::Timebase,
572        new_source_clock: &cm::Clock,
573    ) -> os::Status;
574
575    fn CMTimebaseSetSourceTimebase(
576        timebase: &mut cm::Timebase,
577        new_source_timebase: &cm::Timebase,
578    ) -> os::Status;
579
580    static kCMTimebaseNotification_SourceWillChange: &'static cf::NotificationName;
581    static kCMTimebaseNotification_SourceDidChange: &'static cf::NotificationName;
582    static kCMTimebaseNotification_EffectiveRateChanged: &'static cf::NotificationName;
583    static kCMTimebaseNotification_TimeJumped: &'static cf::NotificationName;
584    static kCMTimebaseNotificationKey_EventTime: &'static cf::String;
585
586    fn CMTimebaseGetTime(timebase: &cm::Timebase) -> cm::Time;
587
588    fn CMTimebaseGetTimeWithTimeScale(
589        timebase: &cm::Timebase,
590        timescale: cm::TimeScale,
591        method: cm::TimeRoundingMethod,
592    ) -> cm::Time;
593
594    fn CMTimebaseSetTime(timebase: &mut cm::Timebase, time: cm::Time) -> os::Status;
595
596    fn CMTimebaseSetAnchorTime(
597        timebase: &mut cm::Timebase,
598        timebase_time: cm::Time,
599        immediate_src_time: cm::Time,
600    ) -> os::Status;
601
602    fn CMTimebaseGetRate(timebase: &cm::Timebase) -> f64;
603
604    fn CMTimebaseGetTimeAndRate(
605        timebase: &cm::Timebase,
606        time_out: *mut cm::Time,
607        rate_out: *mut f64,
608    ) -> os::Status;
609
610    fn CMTimebaseSetRate(timebase: &mut cm::Timebase, rate: f64) -> os::Status;
611
612    fn CMTimebaseSetRateAndAnchorTime(
613        timebase: &mut cm::Timebase,
614        rate: f64,
615        timebase_time: cm::Time,
616        immediate_src_time: cm::Time,
617    ) -> os::Status;
618
619    fn CMTimebaseGetEffectiveRate(timebase: &cm::Timebase) -> f64;
620
621    fn CMTimebaseAddTimer(
622        timebase: &mut cm::Timebase,
623        timer: &cf::RunLoopTimer,
624        run_loop: &cf::RunLoop,
625    ) -> os::Status;
626
627    fn CMTimebaseRemoveTimer(timebase: &mut cm::Timebase, timer: &cf::RunLoopTimer) -> os::Status;
628
629    fn CMTimebaseSetTimerNextFireTime(
630        timebase: &cm::Timebase,
631        timer: &mut cf::RunLoopTimer,
632        fire_time: cm::Time,
633        flags: u32,
634    ) -> os::Status;
635
636    fn CMTimebaseSetTimerToFireImmediately(
637        timebase: &cm::Timebase,
638        timer: &mut cf::RunLoopTimer,
639    ) -> os::Status;
640
641    #[cfg(feature = "dispatch")]
642    fn CMTimebaseAddTimerDispatchSource(
643        timebase: &mut cm::Timebase,
644        timer_src: &dispatch::TimerSrc,
645    ) -> os::Status;
646
647    #[cfg(feature = "dispatch")]
648    fn CMTimebaseRemoveTimerDispatchSource(
649        timebase: &mut cm::Timebase,
650        timer_src: &dispatch::TimerSrc,
651    ) -> os::Status;
652
653    #[cfg(feature = "dispatch")]
654    fn CMTimebaseSetTimerDispatchSourceNextFireTime(
655        timebase: &mut cm::Timebase,
656        timer_src: &dispatch::TimerSrc,
657        fire_time: cm::Time,
658        flags: u32,
659    ) -> os::Status;
660
661    #[cfg(feature = "dispatch")]
662    fn CMTimebaseSetTimerDispatchSourceToFireImmediately(
663        timebase: &mut cm::Timebase,
664        timer_src: &dispatch::TimerSrc,
665    ) -> os::Status;
666
667    fn CMTimebaseNotificationBarrier(timebase: &cm::Timebase) -> os::Status;
668
669}
670
671impl ClockOrTimebase {
672    /// Queries the relative rate of one timebase or clock relative to another timebase or clock.
673    #[doc(alias = "CMSyncGetRelativeRate")]
674    #[inline]
675    pub fn relative_rate(&self, relative_to: &Self) -> f64 {
676        unsafe { CMSyncGetRelativeRate(self, relative_to) }
677    }
678
679    /// Queries the relative rate of one timebase or clock relative to another timebase or clock and the times of each timebase or
680    /// clock at which the relative rate went into effect.
681    #[doc(alias = "CMSyncGetRelativeRateAndAnchorTime")]
682    #[inline]
683    pub fn relative_rate_and_anchor_time(
684        &self,
685        relative_to: &Self,
686        relative_rate: &mut f64,
687        anchor_time: &mut cm::Time,
688        relative_to_anchor_time: &mut cm::Time,
689    ) -> os::Result {
690        unsafe {
691            CMSyncGetRelativeRateAndAnchorTime(
692                self,
693                relative_to,
694                relative_rate,
695                anchor_time,
696                relative_to_anchor_time,
697            )
698            .result()
699        }
700    }
701
702    /// Converts a time from one timebase or clock to another timebase or clock.
703    ///
704    /// If both have a common source, this calculation is performed purely based on the mathematical rates and offsets
705    /// in the common tree rooted in that source.  
706    /// If they have different source clocks (or are both clocks), this calculation also compensates
707    /// for measured drift between the clocks.
708    /// To convert to or from host time, pass cm::Clock::host_time_clock() as the appropriate argument.
709    #[doc(alias = "CMSyncConvertTime")]
710    #[inline]
711    pub fn convert_time_to(&self, time: cm::Time, to: &cm::ClockOrTimebase) -> cm::Time {
712        unsafe { CMSyncConvertTime(time, self, to) }
713    }
714
715    /// Reports whether it is possible for one timebase/clock to drift relative to the other.
716    ///
717    /// A timebase can drift relative to another if their ultimate source clocks that can drift relative
718    /// to each other.
719    #[doc(alias = "CMSyncMightDrift")]
720    #[inline]
721    pub fn might_drift(&self, other: &Self) -> bool {
722        unsafe { CMSyncMightDrift(self, other) }
723    }
724
725    /// A helper function to get time from a clock or timebase.  
726    #[doc(alias = "CMSyncGetTime")]
727    #[inline]
728    pub fn time(&self) -> cm::Time {
729        unsafe { CMSyncGetTime(self) }
730    }
731}
732
733unsafe extern "C-unwind" {
734
735    fn CMSyncGetRelativeRate(
736        of_clock_or_timebase: &cm::ClockOrTimebase,
737        relative_to_clock_or_timebase: &cm::ClockOrTimebase,
738    ) -> f64;
739
740    fn CMSyncGetRelativeRateAndAnchorTime(
741        of_clock_or_timebase: &cm::ClockOrTimebase,
742        relative_to_clock_or_timebase: &cm::ClockOrTimebase,
743        out_relative_rate: *mut f64,
744        out_of_clock_or_timebase_anchor_time: *mut cm::Time,
745        out_relative_to_clock_or_timebase_anchor_time: *mut cm::Time,
746    ) -> os::Status;
747
748    fn CMSyncConvertTime(
749        time: cm::Time,
750        from: &cm::ClockOrTimebase,
751        to: &cm::ClockOrTimebase,
752    ) -> cm::Time;
753
754    fn CMSyncMightDrift(a: &cm::ClockOrTimebase, b: &cm::ClockOrTimebase) -> bool;
755
756    fn CMSyncGetTime(a: &cm::ClockOrTimebase) -> cm::Time;
757
758}