vst3/
support.rs

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
122/// Constructs a 16-byte [`TUID`] value from four 32-bit integers.
123///
124/// Note that the byte order of the resulting value will differ between Windows and other
125/// platforms.
126pub 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;