Mercurial > hg > pub > prymula > com
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/travesty/base.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,224 @@ +/* + * travesty, pure C VST3-compatible interface + * Copyright (C) 2021-2022 Filipe Coelho <falktx@falktx.com> + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#pragma once + +#include <stdbool.h> +#include <stdint.h> +#include <string.h> + +/** + * deal with C vs C++ differences + */ + +#if !defined(__cplusplus) && !defined(constexpr) +# define constexpr +#endif + +/** + * various types + */ + +typedef int32_t v3_result; + +typedef int16_t v3_str_128[128]; +typedef uint8_t v3_bool; + +typedef uint32_t v3_param_id; + +/** + * low-level ABI nonsense + */ + +typedef uint8_t v3_tuid[16]; + +static inline +bool v3_tuid_match(const v3_tuid a, const v3_tuid b) +{ + return memcmp(a, b, sizeof(v3_tuid)) == 0; +} + +#if defined(_WIN32) +# define V3_COM_COMPAT 1 +# define V3_API __stdcall +#else +# define V3_COM_COMPAT 0 +# define V3_API +#endif + +#if V3_COM_COMPAT +enum { + V3_NO_INTERFACE = 0x80004002L, + V3_OK = 0, + V3_TRUE = 0, + V3_FALSE = 1, + V3_INVALID_ARG = 0x80070057L, + V3_NOT_IMPLEMENTED = 0x80004001L, + V3_INTERNAL_ERR = 0x80004005L, + V3_NOT_INITIALIZED = 0x8000FFFFL, + V3_NOMEM = 0x8007000EL +}; + +# define V3_ID(a, b, c, d) { \ + ((a) & 0x000000FF), \ + ((a) & 0x0000FF00) >> 8, \ + ((a) & 0x00FF0000) >> 16, \ + ((a) & 0xFF000000) >> 24, \ + \ + ((b) & 0x00FF0000) >> 16, \ + ((b) & 0xFF000000) >> 24, \ + ((b) & 0x000000FF), \ + ((b) & 0x0000FF00) >> 8, \ + \ + ((c) & 0xFF000000) >> 24, \ + ((c) & 0x00FF0000) >> 16, \ + ((c) & 0x0000FF00) >> 8, \ + ((c) & 0x000000FF), \ + \ + ((d) & 0xFF000000) >> 24, \ + ((d) & 0x00FF0000) >> 16, \ + ((d) & 0x0000FF00) >> 8, \ + ((d) & 0x000000FF), \ +} + +#else // V3_COM_COMPAT +enum { + V3_NO_INTERFACE = -1, + V3_OK, + V3_TRUE = V3_OK, + V3_FALSE, + V3_INVALID_ARG, + V3_NOT_IMPLEMENTED, + V3_INTERNAL_ERR, + V3_NOT_INITIALIZED, + V3_NOMEM +}; + +# define V3_ID(a, b, c, d) { \ + ((a) & 0xFF000000) >> 24, \ + ((a) & 0x00FF0000) >> 16, \ + ((a) & 0x0000FF00) >> 8, \ + ((a) & 0x000000FF), \ + \ + ((b) & 0xFF000000) >> 24, \ + ((b) & 0x00FF0000) >> 16, \ + ((b) & 0x0000FF00) >> 8, \ + ((b) & 0x000000FF), \ + \ + ((c) & 0xFF000000) >> 24, \ + ((c) & 0x00FF0000) >> 16, \ + ((c) & 0x0000FF00) >> 8, \ + ((c) & 0x000000FF), \ + \ + ((d) & 0xFF000000) >> 24, \ + ((d) & 0x00FF0000) >> 16, \ + ((d) & 0x0000FF00) >> 8, \ + ((d) & 0x000000FF), \ +} +#endif // V3_COM_COMPAT + +#define V3_ID_COPY(iid) \ + { iid[0], iid[1], iid[ 2], iid[ 3], iid[ 4], iid[ 5], iid[ 6], iid[ 7], \ + iid[8], iid[9], iid[10], iid[11], iid[12], iid[13], iid[14], iid[15] } + +/** + * funknown + */ + +struct v3_funknown { + v3_result (V3_API* query_interface)(void* self, const v3_tuid iid, void** obj); + uint32_t (V3_API* ref)(void* self); + uint32_t (V3_API* unref)(void* self); +}; + +static constexpr const v3_tuid v3_funknown_iid = + V3_ID(0x00000000, 0x00000000, 0xC0000000, 0x00000046); + +/** + * plugin base + */ + +struct v3_plugin_base { +#ifndef __cplusplus + struct v3_funknown; +#endif + v3_result (V3_API* initialize)(void* self, struct v3_funknown** context); + v3_result (V3_API* terminate)(void* self); +}; + +static constexpr const v3_tuid v3_plugin_base_iid = + V3_ID(0x22888DDB, 0x156E45AE, 0x8358B348, 0x08190625); + +#ifdef __cplusplus + +/** + * cast object into its proper C++ type. + * this is needed because `struct v3_funknown;` on a C++ class does not inherit `v3_funknown`'s fields. + * + * we can use this as a little helper for keeping both C and C++ compatiblity. + * specialized templated calls are defined where required + * (that is, object inherits from something other than `v3_funknown`) + * + * example usage: `v3_cpp_obj(obj)->method(obj, args...);` + */ + +template<class T> static inline +constexpr T* v3_cpp_obj(T** obj) +{ + /** + * this ugly piece of code is required due to C++ assuming `reinterpret_cast` by default, + * but we need everything to be `static_cast` for it to be `constexpr` compatible. + */ + return static_cast<T*>(static_cast<void*>(static_cast<uint8_t*>(static_cast<void*>(*obj)) + sizeof(void*)*3)); +} + +/** + * helper C++ functions to manually call v3_funknown methods on an object. + */ + +template<class T, class M> static inline +v3_result v3_cpp_obj_query_interface(T** obj, const v3_tuid iid, M*** obj2) +{ + return static_cast<v3_funknown*>(static_cast<void*>(*obj))->query_interface(obj, iid, (void**)obj2); +} + +template<class T> static inline +uint32_t v3_cpp_obj_ref(T** obj) +{ + return static_cast<v3_funknown*>(static_cast<void*>(*obj))->ref(obj); +} + +template<class T> static inline +uint32_t v3_cpp_obj_unref(T** obj) +{ + return static_cast<v3_funknown*>(static_cast<void*>(*obj))->unref(obj); +} + +template<class T> static inline +v3_result v3_cpp_obj_initialize(T** obj, v3_funknown** context) +{ + return static_cast<v3_plugin_base*>( + static_cast<void*>(static_cast<uint8_t*>(static_cast<void*>(*obj)) + sizeof(void*)*3))->initialize(obj, context); +} + +template<class T> static inline +v3_result v3_cpp_obj_terminate(T** obj) +{ + return static_cast<v3_plugin_base*>( + static_cast<void*>(static_cast<uint8_t*>(static_cast<void*>(*obj)) + sizeof(void*)*3))->terminate(obj); +} + +#endif