comparison DPF-Prymula-audioplugins/dpf/distrho/src/travesty/base.h @ 3:84e66ea83026

DPF-Prymula-audioplugins-0.231015-2
author prymula <prymula76@outlook.com>
date Mon, 16 Oct 2023 21:53:34 +0200
parents
children
comparison
equal deleted inserted replaced
2:cf2cb71d31dd 3:84e66ea83026
1 /*
2 * travesty, pure C VST3-compatible interface
3 * Copyright (C) 2021-2022 Filipe Coelho <falktx@falktx.com>
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any purpose with
6 * or without fee is hereby granted, provided that the above copyright notice and this
7 * permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
10 * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
11 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
12 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
13 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17 #pragma once
18
19 #include <stdbool.h>
20 #include <stdint.h>
21 #include <string.h>
22
23 /**
24 * deal with C vs C++ differences
25 */
26
27 #if !defined(__cplusplus) && !defined(constexpr)
28 # define constexpr
29 #endif
30
31 /**
32 * various types
33 */
34
35 typedef int32_t v3_result;
36
37 typedef int16_t v3_str_128[128];
38 typedef uint8_t v3_bool;
39
40 typedef uint32_t v3_param_id;
41
42 /**
43 * low-level ABI nonsense
44 */
45
46 typedef uint8_t v3_tuid[16];
47
48 static inline
49 bool v3_tuid_match(const v3_tuid a, const v3_tuid b)
50 {
51 return memcmp(a, b, sizeof(v3_tuid)) == 0;
52 }
53
54 #if defined(_WIN32)
55 # define V3_COM_COMPAT 1
56 # define V3_API __stdcall
57 #else
58 # define V3_COM_COMPAT 0
59 # define V3_API
60 #endif
61
62 #if V3_COM_COMPAT
63 enum {
64 V3_NO_INTERFACE = 0x80004002L,
65 V3_OK = 0,
66 V3_TRUE = 0,
67 V3_FALSE = 1,
68 V3_INVALID_ARG = 0x80070057L,
69 V3_NOT_IMPLEMENTED = 0x80004001L,
70 V3_INTERNAL_ERR = 0x80004005L,
71 V3_NOT_INITIALIZED = 0x8000FFFFL,
72 V3_NOMEM = 0x8007000EL
73 };
74
75 # define V3_ID(a, b, c, d) { \
76 ((a) & 0x000000FF), \
77 ((a) & 0x0000FF00) >> 8, \
78 ((a) & 0x00FF0000) >> 16, \
79 ((a) & 0xFF000000) >> 24, \
80 \
81 ((b) & 0x00FF0000) >> 16, \
82 ((b) & 0xFF000000) >> 24, \
83 ((b) & 0x000000FF), \
84 ((b) & 0x0000FF00) >> 8, \
85 \
86 ((c) & 0xFF000000) >> 24, \
87 ((c) & 0x00FF0000) >> 16, \
88 ((c) & 0x0000FF00) >> 8, \
89 ((c) & 0x000000FF), \
90 \
91 ((d) & 0xFF000000) >> 24, \
92 ((d) & 0x00FF0000) >> 16, \
93 ((d) & 0x0000FF00) >> 8, \
94 ((d) & 0x000000FF), \
95 }
96
97 #else // V3_COM_COMPAT
98 enum {
99 V3_NO_INTERFACE = -1,
100 V3_OK,
101 V3_TRUE = V3_OK,
102 V3_FALSE,
103 V3_INVALID_ARG,
104 V3_NOT_IMPLEMENTED,
105 V3_INTERNAL_ERR,
106 V3_NOT_INITIALIZED,
107 V3_NOMEM
108 };
109
110 # define V3_ID(a, b, c, d) { \
111 ((a) & 0xFF000000) >> 24, \
112 ((a) & 0x00FF0000) >> 16, \
113 ((a) & 0x0000FF00) >> 8, \
114 ((a) & 0x000000FF), \
115 \
116 ((b) & 0xFF000000) >> 24, \
117 ((b) & 0x00FF0000) >> 16, \
118 ((b) & 0x0000FF00) >> 8, \
119 ((b) & 0x000000FF), \
120 \
121 ((c) & 0xFF000000) >> 24, \
122 ((c) & 0x00FF0000) >> 16, \
123 ((c) & 0x0000FF00) >> 8, \
124 ((c) & 0x000000FF), \
125 \
126 ((d) & 0xFF000000) >> 24, \
127 ((d) & 0x00FF0000) >> 16, \
128 ((d) & 0x0000FF00) >> 8, \
129 ((d) & 0x000000FF), \
130 }
131 #endif // V3_COM_COMPAT
132
133 #define V3_ID_COPY(iid) \
134 { iid[0], iid[1], iid[ 2], iid[ 3], iid[ 4], iid[ 5], iid[ 6], iid[ 7], \
135 iid[8], iid[9], iid[10], iid[11], iid[12], iid[13], iid[14], iid[15] }
136
137 /**
138 * funknown
139 */
140
141 struct v3_funknown {
142 v3_result (V3_API* query_interface)(void* self, const v3_tuid iid, void** obj);
143 uint32_t (V3_API* ref)(void* self);
144 uint32_t (V3_API* unref)(void* self);
145 };
146
147 static constexpr const v3_tuid v3_funknown_iid =
148 V3_ID(0x00000000, 0x00000000, 0xC0000000, 0x00000046);
149
150 /**
151 * plugin base
152 */
153
154 struct v3_plugin_base {
155 #ifndef __cplusplus
156 struct v3_funknown;
157 #endif
158 v3_result (V3_API* initialize)(void* self, struct v3_funknown** context);
159 v3_result (V3_API* terminate)(void* self);
160 };
161
162 static constexpr const v3_tuid v3_plugin_base_iid =
163 V3_ID(0x22888DDB, 0x156E45AE, 0x8358B348, 0x08190625);
164
165 #ifdef __cplusplus
166
167 /**
168 * cast object into its proper C++ type.
169 * this is needed because `struct v3_funknown;` on a C++ class does not inherit `v3_funknown`'s fields.
170 *
171 * we can use this as a little helper for keeping both C and C++ compatiblity.
172 * specialized templated calls are defined where required
173 * (that is, object inherits from something other than `v3_funknown`)
174 *
175 * example usage: `v3_cpp_obj(obj)->method(obj, args...);`
176 */
177
178 template<class T> static inline
179 constexpr T* v3_cpp_obj(T** obj)
180 {
181 /**
182 * this ugly piece of code is required due to C++ assuming `reinterpret_cast` by default,
183 * but we need everything to be `static_cast` for it to be `constexpr` compatible.
184 */
185 return static_cast<T*>(static_cast<void*>(static_cast<uint8_t*>(static_cast<void*>(*obj)) + sizeof(void*)*3));
186 }
187
188 /**
189 * helper C++ functions to manually call v3_funknown methods on an object.
190 */
191
192 template<class T, class M> static inline
193 v3_result v3_cpp_obj_query_interface(T** obj, const v3_tuid iid, M*** obj2)
194 {
195 return static_cast<v3_funknown*>(static_cast<void*>(*obj))->query_interface(obj, iid, (void**)obj2);
196 }
197
198 template<class T> static inline
199 uint32_t v3_cpp_obj_ref(T** obj)
200 {
201 return static_cast<v3_funknown*>(static_cast<void*>(*obj))->ref(obj);
202 }
203
204 template<class T> static inline
205 uint32_t v3_cpp_obj_unref(T** obj)
206 {
207 return static_cast<v3_funknown*>(static_cast<void*>(*obj))->unref(obj);
208 }
209
210 template<class T> static inline
211 v3_result v3_cpp_obj_initialize(T** obj, v3_funknown** context)
212 {
213 return static_cast<v3_plugin_base*>(
214 static_cast<void*>(static_cast<uint8_t*>(static_cast<void*>(*obj)) + sizeof(void*)*3))->initialize(obj, context);
215 }
216
217 template<class T> static inline
218 v3_result v3_cpp_obj_terminate(T** obj)
219 {
220 return static_cast<v3_plugin_base*>(
221 static_cast<void*>(static_cast<uint8_t*>(static_cast<void*>(*obj)) + sizeof(void*)*3))->terminate(obj);
222 }
223
224 #endif