1use std::{
2 mem,
3 ptr::{addr_of_mut, null_mut},
4};
5
6use core_foundation::{
7 base::{kCFAllocatorDefault, CFAllocatorRef, CFGetTypeID, CFRetain, CFType, CFTypeID, CFTypeRef, OSStatus, TCFType, TCFTypeRef},
8 declare_TCFType,
9 dictionary::{CFDictionary, CFDictionaryRef},
10 impl_CFTypeDescription,
11 string::{CFString, CFStringRef},
12};
13use libc::c_void;
14
15pub type VTSessionRef = CFTypeRef;
16
17pub type FrameDelay = i32;
18
19pub const kVTUnlimitedFrameDelayCount: FrameDelay = -1;
20
21extern "C" {
22 pub fn VTSessionCopySupportedPropertyDictionary(session: VTSessionRef, supportedPropertyDictionaryOut: *mut CFDictionaryRef) -> OSStatus;
23
24 pub static kVTPropertyTypeKey: CFStringRef;
25 pub static kVTPropertyType_Enumeration: CFStringRef;
26 pub static kVTPropertyType_Boolean: CFStringRef;
27 pub static kVTPropertyType_Number: CFStringRef;
28 pub static kVTPropertyReadWriteStatusKey: CFStringRef;
29 pub static kVTPropertyReadWriteStatus_ReadOnly: CFStringRef;
30 pub static kVTPropertyReadWriteStatus_ReadWrite: CFStringRef;
31 pub static kVTPropertyShouldBeSerializedKey: CFStringRef;
32 pub static kVTPropertySupportedValueMinimumKey: CFStringRef;
33 pub static kVTPropertySupportedValueMaximumKey: CFStringRef;
34 pub static kVTPropertySupportedValueListKey: CFStringRef;
35 pub static kVTPropertyDocumentationKey: CFStringRef;
36
37 pub fn VTSessionSetProperty(session: VTSessionRef, propertyKey: CFStringRef, propertyValue: CFTypeRef) -> OSStatus;
38 pub fn VTSessionSetProperties(session: VTSessionRef, propertyDictionary: CFDictionaryRef) -> OSStatus;
39 pub fn VTSessionCopyProperty(
40 session: VTSessionRef,
41 propertyKey: CFStringRef,
42 allocator: CFAllocatorRef,
43 propertyValueOut: *mut c_void,
44 ) -> OSStatus;
45 pub fn VTSessionCopySerializableProperties(session: VTSessionRef, allocator: CFAllocatorRef, dictionaryOut: *mut CFDictionaryRef) -> OSStatus;
46}
47
48declare_TCFType!(VTSession, VTSessionRef);
49impl_CFTypeDescription!(VTSession);
50
51impl VTSession {
52 #[inline]
53 pub fn as_concrete_TypeRef(&self) -> VTSessionRef {
54 self.0
55 }
56
57 #[inline]
58 pub fn as_CFType(&self) -> CFType {
59 unsafe { CFType::wrap_under_get_rule(self.as_CFTypeRef()) }
60 }
61
62 #[inline]
63 pub fn as_CFTypeRef(&self) -> CFTypeRef {
64 self.as_concrete_TypeRef() as CFTypeRef
65 }
66
67 #[inline]
68 pub fn into_CFType(self) -> CFType {
69 let reference = self.as_CFTypeRef();
70 mem::forget(self);
71 unsafe { CFType::wrap_under_create_rule(reference) }
72 }
73
74 #[inline]
75 pub unsafe fn wrap_under_create_rule(reference: VTSessionRef) -> VTSession {
76 VTSession(reference)
77 }
78
79 #[inline]
80 pub unsafe fn wrap_under_get_rule(reference: VTSessionRef) -> VTSession {
81 VTSession(CFRetain(reference as CFTypeRef) as VTSessionRef)
82 }
83
84 #[inline]
85 pub fn type_of(&self) -> CFTypeID {
86 unsafe { CFGetTypeID(self.as_CFTypeRef()) }
87 }
88
89 #[inline]
90 pub fn instance_of<T: TCFType>(&self) -> bool {
91 self.type_of() == T::type_id()
92 }
93}
94
95impl Clone for VTSession {
96 #[inline]
97 fn clone(&self) -> VTSession {
98 unsafe { VTSession::wrap_under_get_rule(self.0) }
99 }
100}
101
102impl PartialEq for VTSession {
103 #[inline]
104 fn eq(&self, other: &VTSession) -> bool {
105 self.as_CFType().eq(&other.as_CFType())
106 }
107}
108
109pub trait TVTSession: TCFType {
110 #[inline]
111 fn as_session(&self) -> VTSession {
112 unsafe { VTSession::wrap_under_get_rule(self.as_concrete_TypeRef().as_void_ptr() as VTSessionRef) }
113 }
114
115 #[inline]
116 fn into_session(self) -> VTSession
117 where
118 Self: Sized,
119 {
120 let reference = self.as_concrete_TypeRef().as_void_ptr() as VTSessionRef;
121 mem::forget(self);
122 unsafe { VTSession::wrap_under_create_rule(reference) }
123 }
124}
125
126impl VTSession {
127 #[inline]
128 pub fn downcast<T: TVTSession>(&self) -> Option<T> {
129 if self.instance_of::<T>() {
130 unsafe { Some(T::wrap_under_get_rule(T::Ref::from_void_ptr(self.as_concrete_TypeRef().as_void_ptr()))) }
131 } else {
132 None
133 }
134 }
135
136 #[inline]
137 pub fn downcast_into<T: TVTSession>(self) -> Option<T> {
138 if self.instance_of::<T>() {
139 unsafe {
140 let reference = T::Ref::from_void_ptr(self.as_concrete_TypeRef().as_void_ptr());
141 mem::forget(self);
142 Some(T::wrap_under_create_rule(reference))
143 }
144 } else {
145 None
146 }
147 }
148}
149
150impl VTSession {
151 pub fn copy_supported_property_dictionary(&self) -> Result<CFDictionary<CFString, CFType>, OSStatus> {
152 unsafe {
153 let mut dict: CFDictionaryRef = null_mut();
154 let status = VTSessionCopySupportedPropertyDictionary(self.as_concrete_TypeRef(), &mut dict);
155 if status == 0 {
156 Ok(CFDictionary::wrap_under_create_rule(dict))
157 } else {
158 Err(status)
159 }
160 }
161 }
162
163 pub fn copy_property(&self, property_key: CFString) -> Result<CFType, OSStatus> {
164 unsafe {
165 let mut value: CFTypeRef = null_mut();
166 let status = VTSessionCopyProperty(
167 self.as_concrete_TypeRef(),
168 property_key.as_concrete_TypeRef(),
169 kCFAllocatorDefault,
170 addr_of_mut!(value).cast(),
171 );
172 if status == 0 {
173 Ok(CFType::wrap_under_create_rule(value))
174 } else {
175 Err(status)
176 }
177 }
178 }
179
180 pub fn copy_serializable_properties(&self) -> Result<CFDictionary<CFString, CFType>, OSStatus> {
181 unsafe {
182 let mut dict: CFDictionaryRef = null_mut();
183 let status = VTSessionCopySerializableProperties(self.as_concrete_TypeRef(), kCFAllocatorDefault, &mut dict);
184 if status == 0 {
185 Ok(CFDictionary::wrap_under_create_rule(dict))
186 } else {
187 Err(status)
188 }
189 }
190 }
191
192 pub fn set_property(&self, property_key: CFString, property_value: CFType) -> Result<(), OSStatus> {
193 unsafe {
194 let status = VTSessionSetProperty(self.as_concrete_TypeRef(), property_key.as_concrete_TypeRef(), property_value.as_concrete_TypeRef());
195 if status == 0 {
196 Ok(())
197 } else {
198 Err(status)
199 }
200 }
201 }
202
203 pub fn set_properties(&self, property_dictionary: &CFDictionary<CFString, CFType>) -> Result<(), OSStatus> {
204 unsafe {
205 let status = VTSessionSetProperties(self.as_concrete_TypeRef(), property_dictionary.as_concrete_TypeRef());
206 if status == 0 {
207 Ok(())
208 } else {
209 Err(status)
210 }
211 }
212 }
213}