core_media/
time.rs

1use core_foundation::{
2    base::{kCFAllocatorDefault, CFAllocatorRef, TCFType},
3    dictionary::{CFDictionary, CFDictionaryRef},
4    number::CFNumber,
5    string::{CFString, CFStringRef},
6};
7#[cfg(feature = "objc")]
8use objc2::encode::{Encode, Encoding};
9
10pub type CMTimeValue = i64;
11pub type CMTimeScale = i32;
12pub type CMTimeEpoch = i64;
13pub type CMTimeFlags = u32;
14
15pub const kCMTimeFlags_Valid: CMTimeFlags = 1 << 0;
16pub const kCMTimeFlags_HasBeenRounded: CMTimeFlags = 1 << 1;
17pub const kCMTimeFlags_PositiveInfinity: CMTimeFlags = 1 << 2;
18pub const kCMTimeFlags_NegativeInfinity: CMTimeFlags = 1 << 3;
19pub const kCMTimeFlags_Indefinite: CMTimeFlags = 1 << 4;
20pub const kCMTimeFlags_ImpliedValueFlagsMask: CMTimeFlags = kCMTimeFlags_PositiveInfinity | kCMTimeFlags_NegativeInfinity | kCMTimeFlags_Indefinite;
21
22#[repr(C, align(4))]
23#[derive(Clone, Copy, Debug, Default, PartialEq)]
24pub struct CMTime {
25    pub value: CMTimeValue,
26    pub timescale: CMTimeScale,
27    pub flags: CMTimeFlags,
28    pub epoch: CMTimeEpoch,
29}
30
31extern "C" {
32    pub static kCMTimeInvalid: CMTime;
33    pub static kCMTimeIndefinite: CMTime;
34    pub static kCMTimePositiveInfinity: CMTime;
35    pub static kCMTimeNegativeInfinity: CMTime;
36    pub static kCMTimeZero: CMTime;
37
38    pub fn CMTimeMake(value: CMTimeValue, timescale: CMTimeScale) -> CMTime;
39    pub fn CMTimeMakeWithEpoch(value: CMTimeValue, timescale: CMTimeScale, epoch: CMTimeEpoch) -> CMTime;
40    pub fn CMTimeMakeWithSeconds(seconds: f64, preferredTimeScale: i32) -> CMTime;
41    pub fn CMTimeGetSeconds(time: CMTime) -> f64;
42}
43
44pub type CMTimeRoundingMethod = u32;
45
46pub const kCMTimeRoundingMethod_RoundHalfAwayFromZero: CMTimeRoundingMethod = 1;
47pub const kCMTimeRoundingMethod_RoundTowardZero: CMTimeRoundingMethod = 2;
48pub const kCMTimeRoundingMethod_RoundAwayFromZero: CMTimeRoundingMethod = 3;
49pub const kCMTimeRoundingMethod_QuickTime: CMTimeRoundingMethod = 4;
50pub const kCMTimeRoundingMethod_RoundTowardPositiveInfinity: CMTimeRoundingMethod = 5;
51pub const kCMTimeRoundingMethod_RoundTowardNegativeInfinity: CMTimeRoundingMethod = 6;
52pub const kCMTimeRoundingMethod_Default: CMTimeRoundingMethod = kCMTimeRoundingMethod_RoundHalfAwayFromZero;
53
54extern "C" {
55    pub fn CMTimeConvertScale(time: CMTime, newTimescale: CMTimeScale, method: CMTimeRoundingMethod) -> CMTime;
56    pub fn CMTimeAdd(lhs: CMTime, rhs: CMTime) -> CMTime;
57    pub fn CMTimeSubtract(lhs: CMTime, rhs: CMTime) -> CMTime;
58    pub fn CMTimeMultiply(time: CMTime, multiplier: i32) -> CMTime;
59    pub fn CMTimeMultiplyByFloat64(time: CMTime, multiplier: f64) -> CMTime;
60    pub fn CMTimeMultiplyByRatio(time: CMTime, multiplier: i32, divisor: i32) -> CMTime;
61    pub fn CMTimeCompare(time1: CMTime, time2: CMTime) -> i32;
62    pub fn CMTimeMinimum(time1: CMTime, time2: CMTime) -> CMTime;
63    pub fn CMTimeMaximum(time1: CMTime, time2: CMTime) -> CMTime;
64    pub fn CMTimeAbsoluteValue(time: CMTime) -> CMTime;
65    pub fn CMTimeCopyAsDictionary(time: CMTime, allocator: CFAllocatorRef) -> CFDictionaryRef;
66    pub fn CMTimeMakeFromDictionary(dictionaryRepresentation: CFDictionaryRef) -> CMTime;
67
68    pub static kCMTimeValueKey: CFStringRef;
69    pub static kCMTimeScaleKey: CFStringRef;
70    pub static kCMTimeEpochKey: CFStringRef;
71    pub static kCMTimeFlagsKey: CFStringRef;
72
73    pub fn CMTimeCopyDescription(allocator: CFAllocatorRef, time: CMTime) -> CFStringRef;
74    pub fn CMTimeShow(time: CMTime);
75}
76
77#[cfg(feature = "objc")]
78unsafe impl Encode for CMTime {
79    const ENCODING: Encoding = Encoding::Struct("?", &[CMTimeValue::ENCODING, CMTimeScale::ENCODING, CMTimeFlags::ENCODING, CMTimeEpoch::ENCODING]);
80}
81
82impl CMTime {
83    #[inline]
84    pub fn make(value: CMTimeValue, timescale: CMTimeScale) -> Self {
85        unsafe { CMTimeMake(value, timescale) }
86    }
87
88    #[inline]
89    pub fn make_with_epoch(value: CMTimeValue, timescale: CMTimeScale, epoch: CMTimeEpoch) -> Self {
90        unsafe { CMTimeMakeWithEpoch(value, timescale, epoch) }
91    }
92
93    #[inline]
94    pub fn make_with_seconds(seconds: f64, preferred_time_scale: i32) -> Self {
95        unsafe { CMTimeMakeWithSeconds(seconds, preferred_time_scale) }
96    }
97
98    #[inline]
99    pub fn get_seconds(&self) -> f64 {
100        unsafe { CMTimeGetSeconds(*self) }
101    }
102
103    #[inline]
104    pub fn convert_scale(&self, new_timescale: CMTimeScale, method: CMTimeRoundingMethod) -> Self {
105        unsafe { CMTimeConvertScale(*self, new_timescale, method) }
106    }
107
108    #[inline]
109    pub fn add(&self, time: CMTime) -> Self {
110        unsafe { CMTimeAdd(*self, time) }
111    }
112
113    #[inline]
114    pub fn subtract(&self, time: CMTime) -> Self {
115        unsafe { CMTimeSubtract(*self, time) }
116    }
117
118    #[inline]
119    pub fn multiply(&self, multiplier: i32) -> Self {
120        unsafe { CMTimeMultiply(*self, multiplier) }
121    }
122
123    #[inline]
124    pub fn multiply_by_float64(&self, multiplier: f64) -> Self {
125        unsafe { CMTimeMultiplyByFloat64(*self, multiplier) }
126    }
127
128    #[inline]
129    pub fn multiply_by_ratio(&self, multiplier: i32, divisor: i32) -> Self {
130        unsafe { CMTimeMultiplyByRatio(*self, multiplier, divisor) }
131    }
132
133    #[inline]
134    pub fn compare(&self, time: CMTime) -> i32 {
135        unsafe { CMTimeCompare(*self, time) }
136    }
137
138    #[inline]
139    pub fn minimum(&self, time: CMTime) -> Self {
140        unsafe { CMTimeMinimum(*self, time) }
141    }
142
143    #[inline]
144    pub fn maximum(&self, time: CMTime) -> Self {
145        unsafe { CMTimeMaximum(*self, time) }
146    }
147
148    #[inline]
149    pub fn absolute_value(&self) -> Self {
150        unsafe { CMTimeAbsoluteValue(*self) }
151    }
152
153    #[inline]
154    pub fn copy_as_dictionary(&self) -> Option<CFDictionary<CFString, CFNumber>> {
155        unsafe {
156            let dict = CMTimeCopyAsDictionary(*self, kCFAllocatorDefault);
157            if dict.is_null() {
158                None
159            } else {
160                Some(TCFType::wrap_under_create_rule(dict))
161            }
162        }
163    }
164
165    #[inline]
166    pub fn make_from_dictionary(dictionary_representation: &CFDictionary<CFString, CFNumber>) -> Self {
167        unsafe { CMTimeMakeFromDictionary(dictionary_representation.as_concrete_TypeRef()) }
168    }
169
170    #[inline]
171    pub fn copy_description(&self) -> Option<CFString> {
172        unsafe {
173            let description = CMTimeCopyDescription(kCFAllocatorDefault, *self);
174            if description.is_null() {
175                None
176            } else {
177                Some(TCFType::wrap_under_create_rule(description))
178            }
179        }
180    }
181
182    #[inline]
183    pub fn show(&self) {
184        unsafe { CMTimeShow(*self) }
185    }
186}