1use std::ffi::c_void;
2
3use com_scrape_types::{Class, Construct, Guid, Header, InterfaceList, Wrapper};
4
5use crate::Steinberg::{int8, tresult, uint32, FUnknown, FUnknownVtbl, TUID};
6
7pub const fn tuid_as_guid(tuid: TUID) -> Guid {
8 [
9 tuid[0] as u8,
10 tuid[1] as u8,
11 tuid[2] as u8,
12 tuid[3] as u8,
13 tuid[4] as u8,
14 tuid[5] as u8,
15 tuid[6] as u8,
16 tuid[7] as u8,
17 tuid[8] as u8,
18 tuid[9] as u8,
19 tuid[10] as u8,
20 tuid[11] as u8,
21 tuid[12] as u8,
22 tuid[13] as u8,
23 tuid[14] as u8,
24 tuid[15] as u8,
25 ]
26}
27
28#[inline]
29pub unsafe fn FUnknown_query_interface(this: *mut c_void, iid: &Guid) -> Option<*mut c_void> {
30 let ptr = this as *mut FUnknown;
31 let mut obj = std::ptr::null_mut();
32 let result = ((*(*ptr).vtbl).queryInterface)(ptr, iid.as_ptr() as *const TUID, &mut obj);
33
34 if result == kResultOk {
35 Some(obj)
36 } else {
37 None
38 }
39}
40
41#[inline]
42pub unsafe fn FUnknown_add_ref(this: *mut c_void) -> usize {
43 let ptr = this as *mut FUnknown;
44 ((*(*ptr).vtbl).addRef)(ptr) as usize
45}
46
47#[inline]
48pub unsafe fn FUnknown_release(this: *mut c_void) -> usize {
49 let ptr = this as *mut FUnknown;
50 ((*(*ptr).vtbl).release)(ptr) as usize
51}
52
53impl FUnknown {
54 pub const fn make_vtbl<C, W, const OFFSET: isize>() -> FUnknownVtbl
55 where
56 C: Class,
57 W: Wrapper<C>,
58 {
59 unsafe extern "system" fn queryInterface<C, W, const OFFSET: isize>(
60 this: *mut FUnknown,
61 _iid: *const TUID,
62 obj: *mut *mut c_void,
63 ) -> tresult
64 where
65 C: Class,
66 W: Wrapper<C>,
67 {
68 let header_ptr = (this as *mut u8).offset(-OFFSET) as *mut Header<C>;
69 if let Some(result) = C::Interfaces::query(&*(_iid as *const Guid)) {
70 let ptr = W::data_from_header(header_ptr);
71 W::add_ref(ptr);
72
73 std::ptr::write_unaligned(
74 obj,
75 (header_ptr as *mut u8).offset(result) as *mut c_void,
76 );
77
78 kResultOk
79 } else {
80 kNoInterface
81 }
82 }
83
84 unsafe extern "system" fn addRef<C, W, const OFFSET: isize>(this: *mut FUnknown) -> uint32
85 where
86 C: Class,
87 W: Wrapper<C>,
88 {
89 let header_ptr = (this as *mut u8).offset(-OFFSET) as *mut Header<C>;
90 let ptr = W::data_from_header(header_ptr);
91 W::add_ref(ptr) as uint32
92 }
93
94 unsafe extern "system" fn release<C, W, const OFFSET: isize>(this: *mut FUnknown) -> uint32
95 where
96 C: Class,
97 W: Wrapper<C>,
98 {
99 let header_ptr = (this as *mut u8).offset(-OFFSET) as *mut Header<C>;
100 let ptr = W::data_from_header(header_ptr);
101 W::release(ptr) as uint32
102 }
103
104 FUnknownVtbl {
105 queryInterface: queryInterface::<C, W, OFFSET>,
106 addRef: addRef::<C, W, OFFSET>,
107 release: release::<C, W, OFFSET>,
108 }
109 }
110}
111
112unsafe impl<C, W, const OFFSET: isize> Construct<C, W, OFFSET> for FUnknown
113where
114 C: Class,
115 W: Wrapper<C>,
116{
117 const OBJ: FUnknown = FUnknown {
118 vtbl: &Self::make_vtbl::<C, W, OFFSET>(),
119 };
120}
121
122pub const fn uid(a: u32, b: u32, c: u32, d: u32) -> TUID {
127 uid_impl(a, b, c, d)
128}
129
130#[cfg(target_os = "windows")]
131const fn uid_impl(a: u32, b: u32, c: u32, d: u32) -> TUID {
132 [
133 ((a & 0x000000FF) >> 0) as int8,
134 ((a & 0x0000FF00) >> 8) as int8,
135 ((a & 0x00FF0000) >> 16) as int8,
136 ((a & 0xFF000000) >> 24) as int8,
137 ((b & 0x00FF0000) >> 16) as int8,
138 ((b & 0xFF000000) >> 24) as int8,
139 ((b & 0x000000FF) >> 0) as int8,
140 ((b & 0x0000FF00) >> 8) as int8,
141 ((c & 0xFF000000) >> 24) as int8,
142 ((c & 0x00FF0000) >> 16) as int8,
143 ((c & 0x0000FF00) >> 8) as int8,
144 ((c & 0x000000FF) >> 0) as int8,
145 ((d & 0xFF000000) >> 24) as int8,
146 ((d & 0x00FF0000) >> 16) as int8,
147 ((d & 0x0000FF00) >> 8) as int8,
148 ((d & 0x000000FF) >> 0) as int8,
149 ]
150}
151
152#[cfg(not(target_os = "windows"))]
153const fn uid_impl(a: u32, b: u32, c: u32, d: u32) -> TUID {
154 [
155 ((a & 0xFF000000) >> 24) as int8,
156 ((a & 0x00FF0000) >> 16) as int8,
157 ((a & 0x0000FF00) >> 8) as int8,
158 ((a & 0x000000FF) >> 0) as int8,
159 ((b & 0xFF000000) >> 24) as int8,
160 ((b & 0x00FF0000) >> 16) as int8,
161 ((b & 0x0000FF00) >> 8) as int8,
162 ((b & 0x000000FF) >> 0) as int8,
163 ((c & 0xFF000000) >> 24) as int8,
164 ((c & 0x00FF0000) >> 16) as int8,
165 ((c & 0x0000FF00) >> 8) as int8,
166 ((c & 0x000000FF) >> 0) as int8,
167 ((d & 0xFF000000) >> 24) as int8,
168 ((d & 0x00FF0000) >> 16) as int8,
169 ((d & 0x0000FF00) >> 8) as int8,
170 ((d & 0x000000FF) >> 0) as int8,
171 ]
172}
173
174#[cfg(target_os = "windows")]
175mod result_values {
176 #![allow(overflowing_literals)]
177
178 use std::ffi::c_int;
179
180 pub const kNoInterface: c_int = 0x80004002;
181 pub const kResultOk: c_int = 0x00000000;
182 pub const kResultTrue: c_int = kResultOk;
183 pub const kResultFalse: c_int = 0x00000001;
184 pub const kInvalidArgument: c_int = 0x80070057;
185 pub const kNotImplemented: c_int = 0x80004001;
186 pub const kInternalError: c_int = 0x80004005;
187 pub const kNotInitialized: c_int = 0x8000FFFF;
188 pub const kOutOfMemory: c_int = 0x8007000E;
189}
190
191#[cfg(not(target_os = "windows"))]
192mod result_values {
193 use std::ffi::c_int;
194
195 pub const kNoInterface: c_int = -1;
196 pub const kResultOk: c_int = 0;
197 pub const kResultTrue: c_int = kResultOk;
198 pub const kResultFalse: c_int = 1;
199 pub const kInvalidArgument: c_int = 2;
200 pub const kNotImplemented: c_int = 3;
201 pub const kInternalError: c_int = 4;
202 pub const kNotInitialized: c_int = 5;
203 pub const kOutOfMemory: c_int = 6;
204}
205
206pub use result_values::*;
207
208#[cfg(target_os = "windows")]
209pub type DefaultEnumType = std::ffi::c_int;
210
211#[cfg(not(target_os = "windows"))]
212pub type DefaultEnumType = std::ffi::c_uint;