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, packed(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}