diff --git a/libs/vst3/LICENSE.txt b/libs/vst3/LICENSE.txt new file mode 100644 index 0000000000..9e57394dde --- /dev/null +++ b/libs/vst3/LICENSE.txt @@ -0,0 +1,41 @@ +//----------------------------------------------------------------------------- +// LICENSE +// (c) 2019, Steinberg Media Technologies GmbH, All Rights Reserved +//----------------------------------------------------------------------------- +This license applies only to files referencing this license, +for other files of the Software Development Kit the respective embedded license text +is applicable. The license can be found at: www.steinberg.net/sdklicenses_vst3 + +This Software Development Kit is licensed under the terms of the Steinberg VST3 License, +or alternatively under the terms of the General Public License (GPL) Version 3. +You may use the Software Development Kit according to either of these licenses as it is +most appropriate for your project on a case-by-case basis (commercial or not). + +a) Proprietary Steinberg VST3 License +The Software Development Kit may not be distributed in parts or its entirety +without prior written agreement by Steinberg Media Technologies GmbH. +The SDK must not be used to re-engineer or manipulate any technology used +in any Steinberg or Third-party application or software module, +unless permitted by law. +Neither the name of the Steinberg Media Technologies GmbH nor the names of its +contributors may be used to endorse or promote products derived from this +software without specific prior written permission. +Before publishing a software under the proprietary license, you need to obtain a copy +of the License Agreement signed by Steinberg Media Technologies GmbH. +The Steinberg VST SDK License Agreement can be found at: +www.steinberg.net/en/company/developers.html + +THE SDK IS PROVIDED BY STEINBERG MEDIA TECHNOLOGIES GMBH "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL STEINBERG MEDIA TECHNOLOGIES GMBH BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +OF THE POSSIBILITY OF SUCH DAMAGE. + +b) General Public License (GPL) Version 3 +Details of these licenses can be found at: www.gnu.org/licenses/gpl-3.0.html +//---------------------------------------------------------------------------------- diff --git a/libs/vst3/pluginterfaces/base/conststringtable.cpp b/libs/vst3/pluginterfaces/base/conststringtable.cpp new file mode 100644 index 0000000000..4891cefa15 --- /dev/null +++ b/libs/vst3/pluginterfaces/base/conststringtable.cpp @@ -0,0 +1,106 @@ +//----------------------------------------------------------------------------- +// Project : SDK Core +// +// Category : SDK Core Interfaces +// Filename : pluginterfaces/base/conststringtable.cpp +// Created by : Steinberg, 09/2007 +// Description : constant unicode string table +// +//----------------------------------------------------------------------------- +// This file is part of a Steinberg SDK. It is subject to the license terms +// in the LICENSE file found in the top-level directory of this distribution +// and at www.steinberg.net/sdklicenses. +// No part of the SDK, including this file, may be copied, modified, propagated, +// or distributed except according to the terms contained in the LICENSE file. +//----------------------------------------------------------------------------- + +#include "conststringtable.h" +#include +#include + +namespace Steinberg { + +static std::map* stringMap; +static std::map* charMap; + +static char16* generateUTF16 (const char8* str); + +//---------------------------------------------------------------------------- +ConstStringTable* ConstStringTable::instance () +{ + static ConstStringTable stringTable; + return &stringTable; +} + +//---------------------------------------------------------------------------- +const char16* ConstStringTable::getString (const char8* str) const +{ + std::map::iterator iter = stringMap->find (str); + if (iter != stringMap->end ()) + return iter->second; + char16* uStr = generateUTF16 (str); + stringMap->insert (std::make_pair (str, uStr)); + return uStr; +} + +//---------------------------------------------------------------------------- +const char16 ConstStringTable::getString (const char8 str) const +{ + std::map::iterator iter = charMap->find (str); + if (iter != charMap->end ()) + return iter->second; + char16 uStr = 0; +#if BYTEORDER == kBigEndian + char8* puStr = (char8*)&uStr; + puStr[1] = str; +#else + uStr = str; +#endif + charMap->insert (std::make_pair (str, uStr)); + return uStr; +} + +//---------------------------------------------------------------------------- +ConstStringTable::ConstStringTable () +{ + stringMap = new std::map; + charMap = new std::map; +} + +//---------------------------------------------------------------------------- +ConstStringTable::~ConstStringTable () +{ + // free out allocated strings + { + std::map::iterator iter = stringMap->begin (); + while (iter != stringMap->end ()) + { + delete[] iter->second; + iter++; + } + } // delete iterator on map before deleting the map + + delete stringMap; + delete charMap; +} + +//---------------------------------------------------------------------------- +char16* generateUTF16 (const char8* str) +{ + int32 len = (int32)strlen (str); + char16* result = new char16[len + 1]; + for (int32 i = 0; i < len; i++) + { +#if BYTEORDER == kBigEndian + char8* pChr = (char8*)&result[i]; + pChr[0] = 0; + pChr[1] = str[i]; +#else + result[i] = str[i]; +#endif + } + result[len] = 0; + return result; +} +//------------------------------------------------------------------------ +} // namespace Steinberg diff --git a/libs/vst3/pluginterfaces/base/conststringtable.h b/libs/vst3/pluginterfaces/base/conststringtable.h new file mode 100644 index 0000000000..177d32712a --- /dev/null +++ b/libs/vst3/pluginterfaces/base/conststringtable.h @@ -0,0 +1,45 @@ +//----------------------------------------------------------------------------- +// Project : SDK Core +// +// Category : SDK Core Interfaces +// Filename : pluginterfaces/base/conststringtable.h +// Created by : Steinberg, 09/2007 +// Description : constant unicode string table +// +//----------------------------------------------------------------------------- +// This file is part of a Steinberg SDK. It is subject to the license terms +// in the LICENSE file found in the top-level directory of this distribution +// and at www.steinberg.net/sdklicenses. +// No part of the SDK, including this file, may be copied, modified, propagated, +// or distributed except according to the terms contained in the LICENSE file. +//----------------------------------------------------------------------------- + +#pragma once + +#include "ftypes.h" + +namespace Steinberg { + +//------------------------------------------------------------------------ +/** Constant unicode string table. +Used for conversion from ASCII string literals to char16. +*/ +//------------------------------------------------------------------------ +class ConstStringTable +{ +public: + static ConstStringTable* instance (); + + /** Returns a char16 string of a ASCII string literal*/ + const char16* getString (const char8* str) const; + /** Returns a char16 character of a ASCII character */ + const char16 getString (const char8 str) const; + +protected: + ConstStringTable (); + ~ConstStringTable (); +}; + +//------------------------------------------------------------------------ +} // namespace Steinberg + diff --git a/libs/vst3/pluginterfaces/base/falignpop.h b/libs/vst3/pluginterfaces/base/falignpop.h new file mode 100644 index 0000000000..8ff7faa790 --- /dev/null +++ b/libs/vst3/pluginterfaces/base/falignpop.h @@ -0,0 +1,25 @@ +//----------------------------------------------------------------------------- +// Project : SDK Core +// +// Category : SDK Core Interfaces +// Filename : pluginterfaces/base/falignpop.h +// Created by : Steinberg, 01/2004 +// Description : Restore alignment settings +// +//----------------------------------------------------------------------------- +// This file is part of a Steinberg SDK. It is subject to the license terms +// in the LICENSE file found in the top-level directory of this distribution +// and at www.steinberg.net/sdklicenses. +// No part of the SDK, including this file, may be copied, modified, propagated, +// or distributed except according to the terms contained in the LICENSE file. +//----------------------------------------------------------------------------- + +//--------------------------------------------------------------------------------------------------- +#if SMTG_OS_MACOS + #pragma pack(pop) +#elif defined __BORLANDC__ + #pragma -a- +#elif SMTG_OS_WINDOWS + #pragma pack(pop) +#endif +//--------------------------------------------------------------------------------------------------- diff --git a/libs/vst3/pluginterfaces/base/falignpush.h b/libs/vst3/pluginterfaces/base/falignpush.h new file mode 100644 index 0000000000..d4ebbade80 --- /dev/null +++ b/libs/vst3/pluginterfaces/base/falignpush.h @@ -0,0 +1,38 @@ +//----------------------------------------------------------------------------- +// Project : SDK Core +// +// Category : SDK Core Interfaces +// Filename : pluginterfaces/base/falignpush.h +// Created by : Steinberg, 01/2004 +// Description : Set alignment settings +// +//----------------------------------------------------------------------------- +// This file is part of a Steinberg SDK. It is subject to the license terms +// in the LICENSE file found in the top-level directory of this distribution +// and at www.steinberg.net/sdklicenses. +// No part of the SDK, including this file, may be copied, modified, propagated, +// or distributed except according to the terms contained in the LICENSE file. +//----------------------------------------------------------------------------- + +//---------------------------------------------------------------------------------------------- +#if SMTG_OS_MACOS + #pragma GCC diagnostic ignored "-Wunknown-warning-option" + #pragma GCC diagnostic ignored "-Wpragma-pack" + #if SMTG_PLATFORM_64 + #pragma pack(push, 16) + #else + #pragma pack(push, 1) + #endif + #pragma GCC diagnostic default "-Wpragma-pack" + #pragma GCC diagnostic default "-Wunknown-warning-option" +#elif defined __BORLANDC__ + #pragma -a8 +#elif SMTG_OS_WINDOWS + #pragma pack(push) + #if SMTG_PLATFORM_64 + #pragma pack(16) + #else + #pragma pack(8) + #endif +#endif +//---------------------------------------------------------------------------------------------- diff --git a/libs/vst3/pluginterfaces/base/fplatform.h b/libs/vst3/pluginterfaces/base/fplatform.h new file mode 100644 index 0000000000..7db1c5d222 --- /dev/null +++ b/libs/vst3/pluginterfaces/base/fplatform.h @@ -0,0 +1,229 @@ +//----------------------------------------------------------------------------- +// Project : SDK Core +// +// Category : SDK Core Interfaces +// Filename : pluginterfaces/base/fplatform.h +// Created by : Steinberg, 01/2004 +// Description : Detect platform and set define +// +//----------------------------------------------------------------------------- +// This file is part of a Steinberg SDK. It is subject to the license terms +// in the LICENSE file found in the top-level directory of this distribution +// and at www.steinberg.net/sdklicenses. +// No part of the SDK, including this file, may be copied, modified, propagated, +// or distributed except according to the terms contained in the LICENSE file. +//----------------------------------------------------------------------------- + +#pragma once + +#define kLittleEndian 0 +#define kBigEndian 1 + +#undef PLUGIN_API + +#if !defined (__INTEL_CXX11_MODE__) +#define SMTG_INTEL_CXX11_MODE 0 +#else +#define SMTG_INTEL_CXX11_MODE __INTEL_CXX11_MODE__ +#endif + +#if !defined (__INTEL_COMPILER) +#define SMTG_INTEL_COMPILER 0 +#else +#define SMTG_INTEL_COMPILER __INTEL_COMPILER +#endif + +//----------------------------------------------------------------------------- +// WIN32 AND WIN64 (WINDOWS) +//----------------------------------------------------------------------------- +#if defined (_WIN32) + //----------------------------------------------------------------------------- + // ARM32 AND ARM64 (WINDOWS) + #if (defined(_M_ARM64) || defined(_M_ARM)) + #define SMTG_OS_WINDOWS_ARM 1 + #endif + + #define SMTG_OS_LINUX 0 + #define SMTG_OS_MACOS 0 + #define SMTG_OS_WINDOWS 1 + #define SMTG_OS_IOS 0 + #define SMTG_OS_OSX 0 + + #define BYTEORDER kLittleEndian + + #define COM_COMPATIBLE 1 + #define PLUGIN_API __stdcall + #define SMTG_PTHREADS 0 + + #ifndef _CRT_SECURE_NO_WARNINGS + #define _CRT_SECURE_NO_WARNINGS + #endif + + #pragma warning (disable : 4244) // Conversion from 'type1' to 'type2', possible loss of data. + #pragma warning (disable : 4250) // Inheritance via dominance is allowed + #pragma warning (disable : 4996) // deprecated functions + + #pragma warning (3 : 4189) // local variable is initialized but not referenced + #pragma warning (3 : 4238) // nonstandard extension used : class rvalue used as lvalue + + #if defined (_WIN64) || defined (_M_ARM64) + #define SMTG_PLATFORM_64 1 + #else + #define SMTG_PLATFORM_64 0 + #endif + + #ifndef WIN32 + #define WIN32 1 + #endif + + #ifdef __cplusplus + #define SMTG_CPP11 __cplusplus >= 201103L || _MSC_VER > 1600 || SMTG_INTEL_CXX11_MODE + #define SMTG_CPP11_STDLIBSUPPORT SMTG_CPP11 + #define SMTG_HAS_NOEXCEPT _MSC_VER >= 1900 || (SMTG_INTEL_CXX11_MODE && SMTG_INTEL_COMPILER >= 1300) + #endif + + #define SMTG_DEPRECATED_ATTRIBUTE(message) __declspec (deprecated ("Is Deprecated: " message)) +//----------------------------------------------------------------------------- +// LINUX +//----------------------------------------------------------------------------- +#elif __gnu_linux__ + #define SMTG_OS_LINUX 1 + #define SMTG_OS_MACOS 0 + #define SMTG_OS_WINDOWS 0 + #define SMTG_OS_IOS 0 + #define SMTG_OS_OSX 0 + + #include + #if __BYTE_ORDER == __LITTLE_ENDIAN + #define BYTEORDER kLittleEndian + #else + #define BYTEORDER kBigEndian + #endif + + #define COM_COMPATIBLE 0 + #define PLUGIN_API + #define SMTG_PTHREADS 1 + + #if __LP64__ + #define SMTG_PLATFORM_64 1 + #else + #define SMTG_PLATFORM_64 0 + #endif + #ifdef __cplusplus + #include + #define SMTG_CPP11 (__cplusplus >= 201103L) + #ifndef SMTG_CPP11 + #error unsupported compiler + #endif + #define SMTG_CPP11_STDLIBSUPPORT SMTG_CPP11 + #define SMTG_HAS_NOEXCEPT SMTG_CPP11 + #endif +//----------------------------------------------------------------------------- +// Mac and iOS +//----------------------------------------------------------------------------- +#elif __APPLE__ + #include + #define SMTG_OS_LINUX 0 + #define SMTG_OS_MACOS 1 + #define SMTG_OS_WINDOWS 0 + #define SMTG_OS_IOS TARGET_OS_IPHONE + #define SMTG_OS_OSX TARGET_OS_MAC && !TARGET_OS_IPHONE + + #if !SMTG_OS_IOS + #ifndef __CF_USE_FRAMEWORK_INCLUDES__ + #define __CF_USE_FRAMEWORK_INCLUDES__ + #endif + #ifndef TARGET_API_MAC_CARBON + #define TARGET_API_MAC_CARBON 1 + #endif + #endif + #if __LP64__ + #define SMTG_PLATFORM_64 1 + #else + #define SMTG_PLATFORM_64 0 + #endif + #if defined (__BIG_ENDIAN__) + #define BYTEORDER kBigEndian + #else + #define BYTEORDER kLittleEndian + #endif + + #define COM_COMPATIBLE 0 + #define PLUGIN_API + #define SMTG_PTHREADS 1 + + #if !defined(__PLIST__) && !defined(SMTG_DISABLE_DEFAULT_DIAGNOSTICS) + #ifdef __clang__ + #pragma GCC diagnostic ignored "-Wswitch-enum" + #pragma GCC diagnostic ignored "-Wparentheses" + #pragma GCC diagnostic ignored "-Wuninitialized" + #if __clang_major__ >= 3 + #pragma GCC diagnostic ignored "-Wtautological-compare" + #pragma GCC diagnostic ignored "-Wunused-value" + #if __clang_major__ >= 4 || __clang_minor__ >= 1 + #pragma GCC diagnostic ignored "-Wswitch" + #pragma GCC diagnostic ignored "-Wcomment" + #endif + #if __clang_major__ >= 5 + #pragma GCC diagnostic ignored "-Wunsequenced" + #if __clang_minor__ >= 1 + #pragma GCC diagnostic ignored "-Wunused-const-variable" + #endif + #endif + #endif + #endif + #endif + #ifdef __cplusplus + #include + #define SMTG_CPP11 (__cplusplus >= 201103L || SMTG_INTEL_CXX11_MODE) + #if defined (_LIBCPP_VERSION) && SMTG_CPP11 + #define SMTG_CPP11_STDLIBSUPPORT 1 + #define SMTG_HAS_NOEXCEPT 1 + #else + #define SMTG_CPP11_STDLIBSUPPORT 0 + #define SMTG_HAS_NOEXCEPT 0 + #endif + #endif +#else + #pragma error unknown platform +#endif + +//----------------------------------------------------------------------------- +#if !SMTG_RENAME_ASSERT +#undef WINDOWS +#undef MAC +#undef PTHREADS +#undef PLATFORM_64 + +#if SMTG_OS_WINDOWS +#define WINDOWS SMTG_OS_WINDOWS +#endif +#if SMTG_OS_MACOS +#define MAC SMTG_OS_MACOS +#endif +#define PLATFORM_64 SMTG_PLATFORM_64 +#define PTHREADS SMTG_PTHREADS +#endif +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +#if SMTG_CPP11 +#define SMTG_OVERRIDE override +#else +#define SMTG_OVERRIDE +#endif +#if SMTG_HAS_NOEXCEPT +#define SMTG_NOEXCEPT noexcept +#else +#define SMTG_NOEXCEPT +#endif + +//----------------------------------------------------------------------------- +// Deprecation setting +//----------------------------------------------------------------------------- +#ifndef SMTG_DEPRECATED_ATTRIBUTE +#define SMTG_DEPRECATED_ATTRIBUTE(msg) +#endif + +#define SMTG_DEPRECATED_MSG(msg) SMTG_DEPRECATED_ATTRIBUTE(msg) +//----------------------------------------------------------------------------- diff --git a/libs/vst3/pluginterfaces/base/fstrdefs.h b/libs/vst3/pluginterfaces/base/fstrdefs.h new file mode 100644 index 0000000000..2a5882a051 --- /dev/null +++ b/libs/vst3/pluginterfaces/base/fstrdefs.h @@ -0,0 +1,291 @@ +//----------------------------------------------------------------------------- +// Project : SDK Core +// +// Category : SDK Core Interfaces +// Filename : pluginterfaces/base/fstrdefs.h +// Created by : Steinberg, 01/2004 +// Description : Definitions for handling strings (Unicode / ASCII / Platforms) +// +//----------------------------------------------------------------------------- +// This file is part of a Steinberg SDK. It is subject to the license terms +// in the LICENSE file found in the top-level directory of this distribution +// and at www.steinberg.net/sdklicenses. +// No part of the SDK, including this file, may be copied, modified, propagated, +// or distributed except according to the terms contained in the LICENSE file. +//----------------------------------------------------------------------------- + +#pragma once + +#include "ftypes.h" + +//---------------------------------------------------------------------------- +// string methods defines unicode / ASCII +//---------------------------------------------------------------------------- + +// 16 bit string operations +#if SMTG_CPP11 // if c++11 unicode string literals + #define SMTG_CPP11_CAT_PRIVATE_DONT_USE(a,b) a ## b + #if SMTG_OS_WINDOWS + #define STR16(x) SMTG_CPP11_CAT_PRIVATE_DONT_USE(L,x) + #else + #define STR16(x) SMTG_CPP11_CAT_PRIVATE_DONT_USE(u,x) + #endif +#else + #include "conststringtable.h" + #define STR16(x) Steinberg::ConstStringTable::instance ()->getString (x) +#endif + +#ifdef UNICODE + #define STR(x) STR16(x) + #define tStrBufferSize(buffer) (sizeof(buffer)/sizeof(Steinberg::tchar)) + +#else + #define STR(x) x + #define tStrBufferSize(buffer) (sizeof(buffer)) +#endif + +#define str8BufferSize(buffer) (sizeof(buffer)/sizeof(Steinberg::char8)) +#define str16BufferSize(buffer) (sizeof(buffer)/sizeof(Steinberg::char16)) + +#if SMTG_OS_WINDOWS +#define FORMAT_INT64A "I64d" +#define FORMAT_UINT64A "I64u" + +#elif SMTG_OS_MACOS || SMTG_OS_LINUX +#define FORMAT_INT64A "lld" +#define FORMAT_UINT64A "llu" +#define stricmp strcasecmp +#define strnicmp strncasecmp +#endif + +#ifdef UNICODE +#define FORMAT_INT64W STR(FORMAT_INT64A) +#define FORMAT_UINT64W STR(FORMAT_UINT64A) + +#define FORMAT_INT64 FORMAT_INT64W +#define FORMAT_UINT64 FORMAT_UINT64W +#else +#define FORMAT_INT64 FORMAT_INT64A +#define FORMAT_UINT64 FORMAT_UINT64A +#endif + + +//---------------------------------------------------------------------------- +// newline +//---------------------------------------------------------------------------- +#if SMTG_OS_WINDOWS +#define ENDLINE_A "\r\n" +#define ENDLINE_W STR ("\r\n") +#elif SMTG_OS_MACOS +#define ENDLINE_A "\r" +#define ENDLINE_W STR ("\r") +#elif SMTG_OS_LINUX +#define ENDLINE_A "\n" +#define ENDLINE_W STR ("\n") +#endif + +#ifdef UNICODE +#define ENDLINE ENDLINE_W +#else +#define ENDLINE ENDLINE_A +#endif + +#if SMTG_OS_WINDOWS && !defined(__GNUC__) && defined(_MSC_VER) && (_MSC_VER < 1900) +#define stricmp _stricmp +#define strnicmp _strnicmp +#define snprintf _snprintf +#endif + +namespace Steinberg { + +//---------------------------------------------------------------------------- +static const tchar kEmptyString[] = { 0 }; +static const char8 kEmptyString8[] = { 0 }; +static const char16 kEmptyString16[] = { 0 }; + +#ifdef UNICODE +static const tchar kInfiniteSymbol[] = { 0x221E, 0 }; +#else +static const tchar* const kInfiniteSymbol = STR ("oo"); +#endif + +//---------------------------------------------------------------------------- +template +inline int32 _tstrlen (const T* wcs) +{ + const T* eos = wcs; + + while (*eos++) + ; + + return (int32) (eos - wcs - 1); +} + +inline int32 tstrlen (const tchar* str) {return _tstrlen (str);} +inline int32 strlen8 (const char8* str) {return _tstrlen (str);} +inline int32 strlen16 (const char16* str) {return _tstrlen (str);} + +//---------------------------------------------------------------------------- +template +inline int32 _tstrcmp (const T* src, const T* dst) +{ + while (*src == *dst && *dst) + { + src++; + dst++; + } + + if (*src == 0 && *dst == 0) + return 0; + else if (*src == 0) + return -1; + else if (*dst == 0) + return 1; + else + return (int32) (*src - *dst); +} + +inline int32 tstrcmp (const tchar* src, const tchar* dst) {return _tstrcmp (src, dst);} +inline int32 strcmp8 (const char8* src, const char8* dst) {return _tstrcmp (src, dst);} +inline int32 strcmp16 (const char16* src, const char16* dst) {return _tstrcmp (src, dst);} + +template +inline int32 strcmpT (const T* first, const T* last); + +template <> +inline int32 strcmpT (const char8* first, const char8* last) { return _tstrcmp (first, last); } + +template <> +inline int32 strcmpT (const char16* first, const char16* last) { return _tstrcmp (first, last); } + +//---------------------------------------------------------------------------- +template +inline int32 _tstrncmp (const T* first, const T* last, uint32 count) +{ + if (count == 0) + return 0; + + while (--count && *first && *first == *last) + { + first++; + last++; + } + + if (*first == 0 && *last == 0) + return 0; + else if (*first == 0) + return -1; + else if (*last == 0) + return 1; + else + return (int32) (*first - *last); +} + +inline int32 tstrncmp (const tchar* first, const tchar* last, uint32 count) {return _tstrncmp (first, last, count);} +inline int32 strncmp8 (const char8* first, const char8* last, uint32 count) {return _tstrncmp (first, last, count);} +inline int32 strncmp16 (const char16* first, const char16* last, uint32 count) {return _tstrncmp (first, last, count);} + +template +inline int32 strncmpT (const T* first, const T* last, uint32 count); + +template <> +inline int32 strncmpT (const char8* first, const char8* last, uint32 count) { return _tstrncmp (first, last, count); } + +template <> +inline int32 strncmpT (const char16* first, const char16* last, uint32 count) {return _tstrncmp (first, last, count); } + +//---------------------------------------------------------------------------- +template +inline T* _tstrcpy (T* dst, const T* src) +{ + T* cp = dst; + while ((*cp++ = *src++) != 0) // copy string + ; + return dst; +} +inline tchar* tstrcpy (tchar* dst, const tchar* src) {return _tstrcpy (dst, src);} +inline char8* strcpy8 (char8* dst, const char8* src) {return _tstrcpy (dst, src);} +inline char16* strcpy16 (char16* dst, const char16* src) {return _tstrcpy (dst, src);} + +//---------------------------------------------------------------------------- +template +inline T* _tstrncpy (T* dest, const T* source, uint32 count) +{ + T* start = dest; + while (count && (*dest++ = *source++) != 0) // copy string + count--; + + if (count) // pad out with zeros + { + while (--count) + *dest++ = 0; + } + return start; +} + +inline tchar* tstrncpy (tchar* dest, const tchar* source, uint32 count) {return _tstrncpy (dest, source, count);} +inline char8* strncpy8 (char8* dest, const char8* source, uint32 count) {return _tstrncpy (dest, source, count);} +inline char16* strncpy16 (char16* dest, const char16* source, uint32 count) {return _tstrncpy (dest, source, count);} + +//---------------------------------------------------------------------------- +template +inline T* _tstrcat (T* dst, const T* src) +{ + T* cp = dst; + + while (*cp) + cp++; // find end of dst + + while ((*cp++ = *src++) != 0) // Copy src to end of dst + ; + + return dst; +} + +inline tchar* tstrcat (tchar* dst, const tchar* src) {return _tstrcat (dst, src); } +inline char8* strcat8 (char8* dst, const char8* src) {return _tstrcat (dst, src); } +inline char16* strcat16 (char16* dst, const char16* src) {return _tstrcat (dst, src); } + +//---------------------------------------------------------------------------- +inline void str8ToStr16 (char16* dst, const char8* src, int32 n = -1) +{ + int32 i = 0; + for (;;) + { + if (i == n) + { + dst[i] = 0; + return; + } + +#if BYTEORDER == kBigEndian + char8* pChr = (char8*)&dst[i]; + pChr[0] = 0; + pChr[1] = src[i]; +#else + dst[i] = static_cast (src[i]); +#endif + + if (src[i] == 0) + break; + + i++; + } + + while (n > i) + { + dst[i] = 0; + i++; + } +} + +//------------------------------------------------------------------------ +inline bool FIDStringsEqual (FIDString id1, FIDString id2) +{ + return (id1 && id2) ? (strcmp8 (id1, id2) == 0) : false; +} + +static const uint32 kPrintfBufferSize = 4096; + +//------------------------------------------------------------------------ +} // namespace Steinberg diff --git a/libs/vst3/pluginterfaces/base/ftypes.h b/libs/vst3/pluginterfaces/base/ftypes.h new file mode 100644 index 0000000000..5f61e0ac81 --- /dev/null +++ b/libs/vst3/pluginterfaces/base/ftypes.h @@ -0,0 +1,194 @@ +//----------------------------------------------------------------------------- +// Project : SDK Core +// +// Category : SDK Core Interfaces +// Filename : pluginterfaces/base/ftypes.h +// Created by : Steinberg, 01/2004 +// Description : Basic data types +// +//----------------------------------------------------------------------------- +// This file is part of a Steinberg SDK. It is subject to the license terms +// in the LICENSE file found in the top-level directory of this distribution +// and at www.steinberg.net/sdklicenses. +// No part of the SDK, including this file, may be copied, modified, propagated, +// or distributed except according to the terms contained in the LICENSE file. +//----------------------------------------------------------------------------- + +#pragma once + +#include "fplatform.h" + +//#define UNICODE_OFF // disable / enable unicode + +#ifdef UNICODE_OFF + #ifdef UNICODE + #undef UNICODE + #endif +#else + #define UNICODE 1 +#endif + +#ifdef UNICODE +#define _UNICODE 1 +#endif + +namespace Steinberg +{ +//----------------------------------------------------------------- +// Integral Types + typedef char int8; + typedef unsigned char uint8; + typedef unsigned char uchar; + + typedef short int16; + typedef unsigned short uint16; + +#if SMTG_OS_WINDOWS && !defined(__GNUC__) + typedef long int32; + typedef unsigned long uint32; +#else + typedef int int32; + typedef unsigned int uint32; +#endif + + static const int32 kMaxLong = 0x7fffffff; + static const int32 kMinLong = (-0x7fffffff - 1); + static const int32 kMaxInt32 = kMaxLong; + static const int32 kMinInt32 = kMinLong; + static const uint32 kMaxInt32u = 0xffffffff; + +#if SMTG_OS_WINDOWS && !defined(__GNUC__) + typedef __int64 int64; + typedef unsigned __int64 uint64; + static const int64 kMaxInt64 = 9223372036854775807i64; + static const int64 kMinInt64 = (-9223372036854775807i64 - 1); +#else + typedef long long int64; + typedef unsigned long long uint64; + static const int64 kMaxInt64 = 0x7fffffffffffffffLL; + static const int64 kMinInt64 = (-0x7fffffffffffffffLL-1); +#endif + static const uint64 kMaxInt64u = uint64 (0xffffffff) | (uint64 (0xffffffff) << 32); + +//----------------------------------------------------------------- +// other Semantic Types + typedef int64 TSize; // byte (or other) sizes + typedef int32 tresult; // result code +//----------------------------------------------------------------- + static const float kMaxFloat = 3.40282346638528860E38; + static const double kMaxDouble = 1.7976931348623158E308; + +#if SMTG_PLATFORM_64 + typedef uint64 TPtrInt; +#else + typedef uint32 TPtrInt; +#endif + +//------------------------------------------------------------------ +// Boolean + typedef uint8 TBool; + +//------------------------------------------------------------------ +// Char / Strings + typedef char char8; +#ifdef _NATIVE_WCHAR_T_DEFINED + typedef __wchar_t char16; +#elif defined(__MINGW32__) + typedef wchar_t char16; +#elif SMTG_CPP11 + typedef char16_t char16; +#else + typedef int16 char16; +#endif + +#ifdef UNICODE + typedef char16 tchar; +#else + typedef char8 tchar; +#endif + + typedef const char8* CStringA; + typedef const char16* CStringW; + typedef const tchar* CString; + inline bool strEmpty (const tchar* str) { return (!str || *str == 0); } + inline bool str8Empty (const char8* str) { return (!str || *str == 0); } + inline bool str16Empty (const char16* str) { return (!str || *str == 0); } + + typedef const char8* FIDString; // identifier as string (used for attributes, messages) + + const FIDString kPlatformStringWin = "WIN"; + const FIDString kPlatformStringMac = "MAC"; + const FIDString kPlatformStringIOS = "IOS"; + const FIDString kPlatformStringLinux = "Linux"; +#if SMTG_OS_WINDOWS + const FIDString kPlatformString = kPlatformStringWin; +#elif SMTG_OS_IOS + const FIDString kPlatformString = kPlatformStringIOS; +#elif SMTG_OS_MACOS + const FIDString kPlatformString = kPlatformStringMac; +#elif SMTG_OS_LINUX + const FIDString kPlatformString = kPlatformStringLinux; +#endif + +//------------------------------------------------------------------------ +/** Coordinates */ + typedef int32 UCoord; + static const UCoord kMaxCoord = ((UCoord)0x7FFFFFFF); + static const UCoord kMinCoord = ((UCoord)-0x7FFFFFFF); +} // namespace Steinberg + + +//---------------------------------------------------------------------------- +/** Byte-order Conversion Macros */ +//---------------------------------------------------------------------------- +#define SWAP_32(l) { \ + unsigned char* p = (unsigned char*)& (l); \ + unsigned char t; \ + t = p[0]; p[0] = p[3]; p[3] = t; t = p[1]; p[1] = p[2]; p[2] = t; } + +#define SWAP_16(w) { \ + unsigned char* p = (unsigned char*)& (w); \ + unsigned char t; \ + t = p[0]; p[0] = p[1]; p[1] = t; } + +#define SWAP_64(i) { \ + unsigned char* p = (unsigned char*)& (i); \ + unsigned char t; \ + t = p[0]; p[0] = p[7]; p[7] = t; t = p[1]; p[1] = p[6]; p[6] = t; \ + t = p[2]; p[2] = p[5]; p[5] = t; t = p[3]; p[3] = p[4]; p[4] = t;} + +namespace Steinberg +{ + static inline void FSwap (int8&) {} + static inline void FSwap (uint8&) {} + static inline void FSwap (int16& i16) { SWAP_16 (i16) } + static inline void FSwap (uint16& i16) { SWAP_16 (i16) } + static inline void FSwap (int32& i32) { SWAP_32 (i32) } + static inline void FSwap (uint32& i32) { SWAP_32 (i32) } + static inline void FSwap (int64& i64) { SWAP_64 (i64) } + static inline void FSwap (uint64& i64) { SWAP_64 (i64) } +} + +// always inline macros (only when RELEASE is 1) +//---------------------------------------------------------------------------- +#if RELEASE + #if SMTG_OS_MACOS || SMTG_OS_LINUX + #define SMTG_ALWAYS_INLINE __inline__ __attribute__((__always_inline__)) + #define SMTG_NEVER_INLINE __attribute__((noinline)) + #elif SMTG_OS_WINDOWS + #define SMTG_ALWAYS_INLINE __forceinline + #define SMTG_NEVER_INLINE __declspec(noinline) + #endif +#endif + +#ifndef SMTG_ALWAYS_INLINE + #define SMTG_ALWAYS_INLINE inline +#endif +#ifndef SMTG_NEVER_INLINE + #define SMTG_NEVER_INLINE +#endif + +#ifndef SMTG_CPP11_STDLIBSUPPORT +// Enable this for old compilers +// #define nullptr NULL +#endif diff --git a/libs/vst3/pluginterfaces/base/funknown.cpp b/libs/vst3/pluginterfaces/base/funknown.cpp new file mode 100644 index 0000000000..09d5d27836 --- /dev/null +++ b/libs/vst3/pluginterfaces/base/funknown.cpp @@ -0,0 +1,477 @@ +//----------------------------------------------------------------------------- +// Project : SDK Core +// +// Category : SDK Core Interfaces +// Filename : pluginterfaces/base/funknown.cpp +// Created by : Steinberg, 01/2004 +// Description : Basic Interface +// +//----------------------------------------------------------------------------- +// This file is part of a Steinberg SDK. It is subject to the license terms +// in the LICENSE file found in the top-level directory of this distribution +// and at www.steinberg.net/sdklicenses. +// No part of the SDK, including this file, may be copied, modified, propagated, +// or distributed except according to the terms contained in the LICENSE file. +//----------------------------------------------------------------------------- + +#include "funknown.h" + +#include "fstrdefs.h" + +#include + +#if SMTG_OS_WINDOWS +#include + +#if defined(__MINGW32__) +/* UUID */ +#include +#include +#include +#endif + +#endif + +#if SMTG_OS_MACOS +#include +#include + +#if defined(__GNUC__) && (__GNUC__ >= 4) && !__LP64__ +// on 32 bit Mac OS X we can safely ignore the format warnings as sizeof(int) == sizeof(long) +#pragma GCC diagnostic ignored "-Wformat" +#endif + +#endif + +#if SMTG_OS_LINUX +#include +/* UUID */ +#include +#include +#include +#endif + +namespace Steinberg { + +//------------------------------------------------------------------------ +#if COM_COMPATIBLE +#if SMTG_OS_WINDOWS +#define GuidStruct GUID +#else +struct GuidStruct +{ + uint32 Data1; + uint16 Data2; + uint16 Data3; + uint8 Data4[8]; +}; +#endif +#endif + +static void toString8 (char8* string, const char* data, int32 i1, int32 i2); +static void fromString8 (const char8* string, char* data, int32 i1, int32 i2); +static uint32 makeLong (uint8 b1, uint8 b2, uint8 b3, uint8 b4); + +//------------------------------------------------------------------------ +// FUnknownPrivate +//------------------------------------------------------------------------ +namespace FUnknownPrivate { +//------------------------------------------------------------------------ +int32 PLUGIN_API atomicAdd (int32& var, int32 d) +{ +#if SMTG_OS_WINDOWS + return InterlockedExchangeAdd ((volatile long int*)&var, d) + d; +#elif SMTG_OS_MACOS + return OSAtomicAdd32Barrier (d, (int32_t*)&var); +#elif SMTG_OS_LINUX + __gnu_cxx::__atomic_add (&var, d); + return var; +#else +#warning implement me! + var += d; + return var; +#endif +} +} // FUnknownPrivate + +//------------------------------------------------------------------------ +// FUID implementation +//------------------------------------------------------------------------ + +FUID::FUID () +{ + memset (data, 0, sizeof (TUID)); +} + +//------------------------------------------------------------------------ +FUID::FUID (uint32 l1, uint32 l2, uint32 l3, uint32 l4) +{ + from4Int (l1, l2, l3, l4); +} + +//------------------------------------------------------------------------ +FUID::FUID (const FUID& f) +{ + memcpy (data, f.data, sizeof (TUID)); +} + +//------------------------------------------------------------------------ +#if SMTG_CPP11_STDLIBSUPPORT +FUID::FUID (FUID&& other) +{ + memcpy (data, other.data, sizeof (TUID)); +} + +FUID& FUID::operator= (FUID&& other) +{ + memcpy (data, other.data, sizeof (TUID)); + return *this; +} +#endif + +//------------------------------------------------------------------------ +bool FUID::generate () +{ +#if SMTG_OS_WINDOWS +#if defined(_M_ARM64) || defined(_M_ARM) + //#warning implement me! + return false; +#elif defined(__MINGW32__) + boost::uuids::uuid u = boost::uuids::random_generator()(); + memcpy(data, (const void*)&u, 16); + return true; +#else + GUID guid; + HRESULT hr = CoCreateGuid (&guid); + switch (hr) + { + case RPC_S_OK: memcpy (data, (char*)&guid, sizeof (TUID)); return true; + + case RPC_S_UUID_LOCAL_ONLY: + default: return false; + } +#endif + +#elif SMTG_OS_MACOS + CFUUIDRef uuid = CFUUIDCreate (kCFAllocatorDefault); + if (uuid) + { + CFUUIDBytes bytes = CFUUIDGetUUIDBytes (uuid); + memcpy (data, (char*)&bytes, sizeof (TUID)); + CFRelease (uuid); + return true; + } + return false; + +#elif SMTG_OS_LINUX + boost::uuids::uuid u = boost::uuids::random_generator()(); + memcpy(data, (const void*)&u, 16); + return true; +#else +#warning implement me! + return false; +#endif +} + +//------------------------------------------------------------------------ +bool FUID::isValid () const +{ + TUID nulluid = {0}; + + return memcmp (data, nulluid, sizeof (TUID)) != 0; +} + +//------------------------------------------------------------------------ +FUID& FUID::operator= (const FUID& f) +{ + memcpy (data, f.data, sizeof (TUID)); + return *this; +} + +//------------------------------------------------------------------------ +void FUID::from4Int (uint32 l1, uint32 l2, uint32 l3, uint32 l4) +{ +#if COM_COMPATIBLE + data [0] = (char)((l1 & 0x000000FF) ); + data [1] = (char)((l1 & 0x0000FF00) >> 8); + data [2] = (char)((l1 & 0x00FF0000) >> 16); + data [3] = (char)((l1 & 0xFF000000) >> 24); + data [4] = (char)((l2 & 0x00FF0000) >> 16); + data [5] = (char)((l2 & 0xFF000000) >> 24); + data [6] = (char)((l2 & 0x000000FF) ); + data [7] = (char)((l2 & 0x0000FF00) >> 8); + data [8] = (char)((l3 & 0xFF000000) >> 24); + data [9] = (char)((l3 & 0x00FF0000) >> 16); + data [10] = (char)((l3 & 0x0000FF00) >> 8); + data [11] = (char)((l3 & 0x000000FF) ); + data [12] = (char)((l4 & 0xFF000000) >> 24); + data [13] = (char)((l4 & 0x00FF0000) >> 16); + data [14] = (char)((l4 & 0x0000FF00) >> 8); + data [15] = (char)((l4 & 0x000000FF) ); +#else + data [0] = (char)((l1 & 0xFF000000) >> 24); + data [1] = (char)((l1 & 0x00FF0000) >> 16); + data [2] = (char)((l1 & 0x0000FF00) >> 8); + data [3] = (char)((l1 & 0x000000FF) ); + data [4] = (char)((l2 & 0xFF000000) >> 24); + data [5] = (char)((l2 & 0x00FF0000) >> 16); + data [6] = (char)((l2 & 0x0000FF00) >> 8); + data [7] = (char)((l2 & 0x000000FF) ); + data [8] = (char)((l3 & 0xFF000000) >> 24); + data [9] = (char)((l3 & 0x00FF0000) >> 16); + data [10] = (char)((l3 & 0x0000FF00) >> 8); + data [11] = (char)((l3 & 0x000000FF) ); + data [12] = (char)((l4 & 0xFF000000) >> 24); + data [13] = (char)((l4 & 0x00FF0000) >> 16); + data [14] = (char)((l4 & 0x0000FF00) >> 8); + data [15] = (char)((l4 & 0x000000FF) ); +#endif +} + +//------------------------------------------------------------------------ +void FUID::to4Int (uint32& d1, uint32& d2, uint32& d3, uint32& d4) const +{ + d1 = getLong1 (); + d2 = getLong2 (); + d3 = getLong3 (); + d4 = getLong4 (); +} + +//------------------------------------------------------------------------ +uint32 FUID::getLong1 () const +{ +#if COM_COMPATIBLE + return makeLong (data[3], data[2], data[1], data[0]); +#else + return makeLong (data[0], data[1], data[2], data[3]); +#endif +} + +//------------------------------------------------------------------------ +uint32 FUID::getLong2 () const +{ +#if COM_COMPATIBLE + return makeLong (data[5], data[4], data[7], data[6]); +#else + return makeLong (data[4], data[5], data[6], data[7]); +#endif +} + +//------------------------------------------------------------------------ +uint32 FUID::getLong3 () const +{ +#if COM_COMPATIBLE + return makeLong (data[8], data[9], data[10], data[11]); +#else + return makeLong (data[8], data[9], data[10], data[11]); +#endif +} + +//------------------------------------------------------------------------ +uint32 FUID::getLong4 () const +{ +#if COM_COMPATIBLE + return makeLong (data[12], data[13], data[14], data[15]); +#else + return makeLong (data[12], data[13], data[14], data[15]); +#endif +} + +//------------------------------------------------------------------------ +void FUID::toString (char8* string) const +{ + if (!string) + return; + +#if COM_COMPATIBLE + GuidStruct* g = (GuidStruct*)data; + + char8 s[17]; + Steinberg::toString8 (s, data, 8, 16); + + sprintf (string, "%08X%04X%04X%s", g->Data1, g->Data2, g->Data3, s); +#else + Steinberg::toString8 (string, data, 0, 16); +#endif +} + +//------------------------------------------------------------------------ +bool FUID::fromString (const char8* string) +{ + if (!string || !*string) + return false; + if (strlen (string) != 32) + return false; + +#if COM_COMPATIBLE + GuidStruct g; + char s[33]; + + strcpy (s, string); + s[8] = 0; + sscanf (s, "%x", &g.Data1); + strcpy (s, string + 8); + s[4] = 0; + sscanf (s, "%hx", &g.Data2); + strcpy (s, string + 12); + s[4] = 0; + sscanf (s, "%hx", &g.Data3); + + memcpy (data, &g, 8); + Steinberg::fromString8 (string + 16, data, 8, 16); +#else + Steinberg::fromString8 (string, data, 0, 16); +#endif + + return true; +} + +//------------------------------------------------------------------------ +bool FUID::fromRegistryString (const char8* string) +{ + if (!string || !*string) + return false; + if (strlen (string) != 38) + return false; + +// e.g. {c200e360-38c5-11ce-ae62-08002b2b79ef} + +#if COM_COMPATIBLE + GuidStruct g; + char8 s[10]; + + strncpy (s, string + 1, 8); + s[8] = 0; + sscanf (s, "%x", &g.Data1); + strncpy (s, string + 10, 4); + s[4] = 0; + sscanf (s, "%hx", &g.Data2); + strncpy (s, string + 15, 4); + s[4] = 0; + sscanf (s, "%hx", &g.Data3); + memcpy (data, &g, 8); + + Steinberg::fromString8 (string + 20, data, 8, 10); + Steinberg::fromString8 (string + 25, data, 10, 16); +#else + Steinberg::fromString8 (string + 1, data, 0, 4); + Steinberg::fromString8 (string + 10, data, 4, 6); + Steinberg::fromString8 (string + 15, data, 6, 8); + Steinberg::fromString8 (string + 20, data, 8, 10); + Steinberg::fromString8 (string + 25, data, 10, 16); +#endif + + return true; +} + +//------------------------------------------------------------------------ +void FUID::toRegistryString (char8* string) const +{ +// e.g. {c200e360-38c5-11ce-ae62-08002b2b79ef} + +#if COM_COMPATIBLE + GuidStruct* g = (GuidStruct*)data; + + char8 s1[5]; + Steinberg::toString8 (s1, data, 8, 10); + + char8 s2[13]; + Steinberg::toString8 (s2, data, 10, 16); + + sprintf (string, "{%08X-%04X-%04X-%s-%s}", g->Data1, g->Data2, g->Data3, s1, s2); +#else + char8 s1[9]; + Steinberg::toString8 (s1, data, 0, 4); + char8 s2[5]; + Steinberg::toString8 (s2, data, 4, 6); + char8 s3[5]; + Steinberg::toString8 (s3, data, 6, 8); + char8 s4[5]; + Steinberg::toString8 (s4, data, 8, 10); + char8 s5[13]; + Steinberg::toString8 (s5, data, 10, 16); + + sprintf (string, "{%s-%s-%s-%s-%s}", s1, s2, s3, s4, s5); +#endif +} + +//------------------------------------------------------------------------ +void FUID::print (char8* string, int32 style) const +{ + if (!string) // no string: debug output + { + char8 str[128]; + print (str, style); + +#if SMTG_OS_WINDOWS + OutputDebugStringA (str); + OutputDebugStringA ("\n"); +#else + fprintf (stdout, "%s\n", str); +#endif + return; + } + + uint32 l1, l2, l3, l4; + to4Int (l1, l2, l3, l4); + + switch (style) + { + case kINLINE_UID: + sprintf (string, "INLINE_UID (0x%08X, 0x%08X, 0x%08X, 0x%08X)", l1, l2, l3, l4); + break; + + case kDECLARE_UID: + sprintf (string, "DECLARE_UID (0x%08X, 0x%08X, 0x%08X, 0x%08X)", l1, l2, l3, l4); + break; + + case kFUID: + sprintf (string, "FUID (0x%08X, 0x%08X, 0x%08X, 0x%08X)", l1, l2, l3, l4); + break; + + case kCLASS_UID: + default: + sprintf (string, "DECLARE_CLASS_IID (Interface, 0x%08X, 0x%08X, 0x%08X, 0x%08X)", l1, + l2, l3, l4); + break; + } +} + +//------------------------------------------------------------------------ +// helpers +//------------------------------------------------------------------------ +static uint32 makeLong (uint8 b1, uint8 b2, uint8 b3, uint8 b4) +{ + return (uint32 (b1) << 24) | (uint32 (b2) << 16) | (uint32 (b3) << 8) | uint32 (b4); +} + +//------------------------------------------------------------------------ +static void toString8 (char8* string, const char* data, int32 i1, int32 i2) +{ + *string = 0; + for (int32 i = i1; i < i2; i++) + { + char8 s[3]; + sprintf (s, "%02X", (uint8)data[i]); + strcat (string, s); + } +} + +//------------------------------------------------------------------------ +static void fromString8 (const char8* string, char* data, int32 i1, int32 i2) +{ + for (int32 i = i1; i < i2; i++) + { + char8 s[3]; + s[0] = *string++; + s[1] = *string++; + s[2] = 0; + + int32 d = 0; + sscanf (s, "%2x", &d); + data[i] = (char)d; + } +} + +//------------------------------------------------------------------------ +} // namespace Steinberg diff --git a/libs/vst3/pluginterfaces/base/funknown.h b/libs/vst3/pluginterfaces/base/funknown.h new file mode 100644 index 0000000000..98df20e7b5 --- /dev/null +++ b/libs/vst3/pluginterfaces/base/funknown.h @@ -0,0 +1,475 @@ +//----------------------------------------------------------------------------- +// Project : SDK Core +// +// Category : SDK Core Interfaces +// Filename : pluginterfaces/base/funknown.h +// Created by : Steinberg, 01/2004 +// Description : Basic Interface +// +//----------------------------------------------------------------------------- +// This file is part of a Steinberg SDK. It is subject to the license terms +// in the LICENSE file found in the top-level directory of this distribution +// and at www.steinberg.net/sdklicenses. +// No part of the SDK, including this file, may be copied, modified, propagated, +// or distributed except according to the terms contained in the LICENSE file. +//----------------------------------------------------------------------------- + +#pragma once + +#include "pluginterfaces/base/fplatform.h" +#include "pluginterfaces/base/ftypes.h" +#include "pluginterfaces/base/smartpointer.h" +#include + +//------------------------------------------------------------------------ +/*! \defgroup pluginBase Basic Interfaces +*/ +//------------------------------------------------------------------------ + +//------------------------------------------------------------------------ +// Unique Identifier macros +//------------------------------------------------------------------------ + +#if COM_COMPATIBLE +#define INLINE_UID(l1, l2, l3, l4) \ +{ \ + (::Steinberg::int8)((l1 & 0x000000FF) ), (::Steinberg::int8)((l1 & 0x0000FF00) >> 8), \ + (::Steinberg::int8)((l1 & 0x00FF0000) >> 16), (::Steinberg::int8)((l1 & 0xFF000000) >> 24), \ + (::Steinberg::int8)((l2 & 0x00FF0000) >> 16), (::Steinberg::int8)((l2 & 0xFF000000) >> 24), \ + (::Steinberg::int8)((l2 & 0x000000FF) ), (::Steinberg::int8)((l2 & 0x0000FF00) >> 8), \ + (::Steinberg::int8)((l3 & 0xFF000000) >> 24), (::Steinberg::int8)((l3 & 0x00FF0000) >> 16), \ + (::Steinberg::int8)((l3 & 0x0000FF00) >> 8), (::Steinberg::int8)((l3 & 0x000000FF) ), \ + (::Steinberg::int8)((l4 & 0xFF000000) >> 24), (::Steinberg::int8)((l4 & 0x00FF0000) >> 16), \ + (::Steinberg::int8)((l4 & 0x0000FF00) >> 8), (::Steinberg::int8)((l4 & 0x000000FF) ) \ +} +#else +#define INLINE_UID(l1, l2, l3, l4) \ +{ \ + (::Steinberg::int8)((l1 & 0xFF000000) >> 24), (::Steinberg::int8)((l1 & 0x00FF0000) >> 16), \ + (::Steinberg::int8)((l1 & 0x0000FF00) >> 8), (::Steinberg::int8)((l1 & 0x000000FF) ), \ + (::Steinberg::int8)((l2 & 0xFF000000) >> 24), (::Steinberg::int8)((l2 & 0x00FF0000) >> 16), \ + (::Steinberg::int8)((l2 & 0x0000FF00) >> 8), (::Steinberg::int8)((l2 & 0x000000FF) ), \ + (::Steinberg::int8)((l3 & 0xFF000000) >> 24), (::Steinberg::int8)((l3 & 0x00FF0000) >> 16), \ + (::Steinberg::int8)((l3 & 0x0000FF00) >> 8), (::Steinberg::int8)((l3 & 0x000000FF) ), \ + (::Steinberg::int8)((l4 & 0xFF000000) >> 24), (::Steinberg::int8)((l4 & 0x00FF0000) >> 16), \ + (::Steinberg::int8)((l4 & 0x0000FF00) >> 8), (::Steinberg::int8)((l4 & 0x000000FF) ) \ +} +#endif + +//------------------------------------------------------------------------ +#define DECLARE_UID(name, l1, l2, l3, l4) ::Steinberg::TUID name = INLINE_UID (l1, l2, l3, l4); + +//------------------------------------------------------------------------ +#define EXTERN_UID(name) extern const ::Steinberg::TUID name; + +#ifdef INIT_CLASS_IID +#define DECLARE_CLASS_IID(ClassName, l1, l2, l3, l4) \ + static const ::Steinberg::TUID ClassName##_iid = INLINE_UID (l1, l2, l3, l4); \ + \ +const ::Steinberg::FUID ClassName::iid (ClassName##_iid); +#else +#define DECLARE_CLASS_IID(ClassName, l1, l2, l3, l4) \ + static const ::Steinberg::TUID ClassName##_iid = INLINE_UID (l1, l2, l3, l4); +#endif + +#define DEF_CLASS_IID(ClassName) const ::Steinberg::FUID ClassName::iid (ClassName##_iid); + +#define INLINE_UID_OF(ClassName) ClassName##_iid + +#define INLINE_UID_FROM_FUID(x) \ + INLINE_UID (x.getLong1 (), x.getLong2 (), x.getLong3 (), x.getLong4 ()) + +//------------------------------------------------------------------------ +// FUnknown implementation macros +//------------------------------------------------------------------------ + +#define DECLARE_FUNKNOWN_METHODS \ +public: \ + virtual ::Steinberg::tresult PLUGIN_API queryInterface (const ::Steinberg::TUID _iid, void** obj) SMTG_OVERRIDE; \ + virtual ::Steinberg::uint32 PLUGIN_API addRef () SMTG_OVERRIDE; \ + virtual ::Steinberg::uint32 PLUGIN_API release () SMTG_OVERRIDE; \ +protected : \ + ::Steinberg::int32 __funknownRefCount; \ +public: + +//------------------------------------------------------------------------ + +#define DELEGATE_REFCOUNT(ClassName) \ +public: \ + virtual ::Steinberg::uint32 PLUGIN_API addRef () SMTG_OVERRIDE { return ClassName::addRef (); } \ + virtual ::Steinberg::uint32 PLUGIN_API release () SMTG_OVERRIDE { return ClassName::release (); } + +//------------------------------------------------------------------------ +#define IMPLEMENT_REFCOUNT(ClassName) \ +::Steinberg::uint32 PLUGIN_API ClassName::addRef () \ +{ \ + return ::Steinberg::FUnknownPrivate::atomicAdd (__funknownRefCount, 1); \ +} \ +::Steinberg::uint32 PLUGIN_API ClassName::release () \ +{ \ + if (::Steinberg::FUnknownPrivate::atomicAdd (__funknownRefCount, -1) == 0) \ + { \ + delete this; \ + return 0; \ + } \ + return __funknownRefCount; \ +} + +//------------------------------------------------------------------------ +#define FUNKNOWN_CTOR { __funknownRefCount = 1; } +#define FUNKNOWN_DTOR + +//------------------------------------------------------------------------ +#define QUERY_INTERFACE(iid, obj, InterfaceIID, InterfaceName) \ +if (::Steinberg::FUnknownPrivate::iidEqual (iid, InterfaceIID)) \ +{ \ + addRef (); \ + *obj = static_cast< InterfaceName* >(this); \ + return ::Steinberg::kResultOk; \ +} + +//------------------------------------------------------------------------ +#define IMPLEMENT_QUERYINTERFACE(ClassName, InterfaceName, ClassIID) \ +::Steinberg::tresult PLUGIN_API ClassName::queryInterface (const ::Steinberg::TUID _iid, void** obj)\ +{ \ + QUERY_INTERFACE (_iid, obj, ::Steinberg::FUnknown::iid, InterfaceName) \ + QUERY_INTERFACE (_iid, obj, ClassIID, InterfaceName) \ + *obj = nullptr; \ + return ::Steinberg::kNoInterface; \ +} + +//------------------------------------------------------------------------ +#define IMPLEMENT_FUNKNOWN_METHODS(ClassName,InterfaceName,ClassIID) \ + IMPLEMENT_REFCOUNT (ClassName) \ + IMPLEMENT_QUERYINTERFACE (ClassName, InterfaceName, ClassIID) + +//------------------------------------------------------------------------ +// Result Codes +//------------------------------------------------------------------------ + +namespace Steinberg { + +//------------------------------------------------------------------------ +#if COM_COMPATIBLE +#if SMTG_OS_WINDOWS +enum +{ + kNoInterface = static_cast(0x80004002L), // E_NOINTERFACE + kResultOk = static_cast(0x00000000L), // S_OK + kResultTrue = kResultOk, + kResultFalse = static_cast(0x00000001L), // S_FALSE + kInvalidArgument = static_cast(0x80070057L), // E_INVALIDARG + kNotImplemented = static_cast(0x80004001L), // E_NOTIMPL + kInternalError = static_cast(0x80004005L), // E_FAIL + kNotInitialized = static_cast(0x8000FFFFL), // E_UNEXPECTED + kOutOfMemory = static_cast(0x8007000EL) // E_OUTOFMEMORY +}; +#else +enum +{ + kNoInterface = static_cast(0x80000004L), // E_NOINTERFACE + kResultOk = static_cast(0x00000000L), // S_OK + kResultTrue = kResultOk, + kResultFalse = static_cast(0x00000001L), // S_FALSE + kInvalidArgument = static_cast(0x80000003L), // E_INVALIDARG + kNotImplemented = static_cast(0x80000001L), // E_NOTIMPL + kInternalError = static_cast(0x80000008L), // E_FAIL + kNotInitialized = static_cast(0x8000FFFFL), // E_UNEXPECTED + kOutOfMemory = static_cast(0x80000002L) // E_OUTOFMEMORY +}; +#endif +#else +enum +{ + kNoInterface = -1, + kResultOk, + kResultTrue = kResultOk, + kResultFalse, + kInvalidArgument, + kNotImplemented, + kInternalError, + kNotInitialized, + kOutOfMemory +}; +#endif + +//------------------------------------------------------------------------ +typedef int64 LARGE_INT; // obsolete + +//------------------------------------------------------------------------ +// FUID class declaration +//------------------------------------------------------------------------ +typedef int8 TUID[16]; ///< plain UID type + +//------------------------------------------------------------------------ +/* FUnknown private */ +namespace FUnknownPrivate { +SMTG_ALWAYS_INLINE bool iidEqual (const void* iid1, const void* iid2) +{ + const uint64* p1 = reinterpret_cast (iid1); + const uint64* p2 = reinterpret_cast (iid2); + return p1[0] == p2[0] && p1[1] == p2[1]; +} + +int32 PLUGIN_API atomicAdd (int32& value, int32 amount); +} + +//------------------------------------------------------------------------ +/** Handling 16 Byte Globally Unique Identifiers. +\ingroup pluginBase + +Each interface declares its identifier as static member inside the interface +namespace (e.g. FUnknown::iid). +*/ +//------------------------------------------------------------------------ +class FUID +{ +public: +//------------------------------------------------------------------------ + FUID (); + FUID (uint32 l1, uint32 l2, uint32 l3, uint32 l4); + FUID (const FUID&); + virtual ~FUID () {} + +#if SMTG_CPP11_STDLIBSUPPORT + FUID (FUID&& other); + FUID& operator= (FUID&& other); +#endif + + /** Generates a new Unique Identifier (UID). + Will return true for success. If the return value is false, either no + UID is generated or the UID is not guaranteed to be unique worldwide. */ + bool generate (); + + /** Checks if the UID data is valid. + The default constructor initializes the memory with zeros. */ + bool isValid () const; + + FUID& operator = (const FUID& f); + bool operator == (const FUID& f) const { return ::Steinberg::FUnknownPrivate::iidEqual (data, f.data); } + bool operator < (const FUID& f) const { return memcmp (data, f.data, sizeof (TUID)) < 0; } + bool operator != (const FUID& f) const { return !::Steinberg::FUnknownPrivate::iidEqual (data, f.data); } + + uint32 getLong1 () const; + uint32 getLong2 () const; + uint32 getLong3 () const; + uint32 getLong4 () const; + + void from4Int (uint32 d1, uint32 d2, uint32 d3, uint32 d4); + void to4Int (uint32& d1, uint32& d2, uint32& d3, uint32& d4) const; + + typedef char8 String[64]; + + /** Converts UID to a string. + The string will be 32 characters long, representing the hexadecimal values + of each data byte (e.g. "9127BE30160E4BB69966670AA6087880"). + + Typical use-case is: + \code + char8[33] strUID = {0}; + FUID uid; + if (uid.generate ()) + uid.toString (strUID); + \endcode + */ + void toString (char8* string) const; + + /** Sets the UID data from a string. + The string has to be 32 characters long, where each character-pair is + the ASCII-encoded hexadecimal value of the corresponding data byte. */ + bool fromString (const char8* string); + + /** Converts UID to a string in Microsoft® OLE format. + (e.g. "{c200e360-38c5-11ce-ae62-08002b2b79ef}") */ + void toRegistryString (char8* string) const; + + /** Sets the UID data from a string in Microsoft® OLE format. */ + bool fromRegistryString (const char8* string); + + enum UIDPrintStyle + { + kINLINE_UID, ///< "INLINE_UID (0x00000000, 0x00000000, 0x00000000, 0x00000000)" + kDECLARE_UID, ///< "DECLARE_UID (0x00000000, 0x00000000, 0x00000000, 0x00000000)" + kFUID, ///< "FUID (0x00000000, 0x00000000, 0x00000000, 0x00000000)" + kCLASS_UID ///< "DECLARE_CLASS_IID (Interface, 0x00000000, 0x00000000, 0x00000000, 0x00000000)" + }; + /** Prints the UID to a string (or debug output if string is NULL). + \param string is the output string if not NULL. + \param style can be chosen from the FUID::UIDPrintStyle enumeration. */ + void print (char8* string = nullptr, int32 style = kINLINE_UID) const; + + template + inline explicit FUID (const int8 (&uid)[N]) + { +#if SMTG_CPP11_STDLIBSUPPORT + static_assert (N == sizeof (TUID), "only TUID allowed"); +#endif + memcpy (data, uid, sizeof (TUID)); + } + inline void toTUID (TUID result) const { memcpy (result, data, sizeof (TUID)); } + inline operator const TUID& () const { return data; } + inline const TUID& toTUID () const { return data; } + + static FUID fromTUID (const TUID uid) + { + FUID res; + if (uid) + memcpy (res.data, uid, sizeof (TUID)); + return res; + } + +//------------------------------------------------------------------------ +protected: + TUID data; +}; + +#if SMTG_CPP11_STDLIBSUPPORT +template +inline bool operator== (const FUID& f1, T f2) +{ + static_assert ( + std::is_same::type, FUID>::value, + "Do not compare a FUID with a TUID directly. Either convert the TUID to a FUID and compare them or use FUnknownPrivate::iidEqual"); + return f1.operator== (f2); +} +#endif + +//------------------------------------------------------------------------ +// FUnknown +//------------------------------------------------------------------------ +/** The basic interface of all interfaces. +\ingroup pluginBase + +- The FUnknown::queryInterface method is used to retrieve pointers to other + interfaces of the object. +- FUnknown::addRef and FUnknown::release manage the lifetime of the object. + If no more references exist, the object is destroyed in memory. + +Interfaces are identified by 16 byte Globally Unique Identifiers. +The SDK provides a class called FUID for this purpose. + +\ref howtoClass */ +//------------------------------------------------------------------------ +class FUnknown +{ +public: + +//------------------------------------------------------------------------ + /** Query for a pointer to the specified interface. + Returns kResultOk on success or kNoInterface if the object does not implement the interface. + The object has to call addRef when returning an interface. + \param _iid : (in) 16 Byte interface identifier (-> FUID) + \param obj : (out) On return, *obj points to the requested interface */ + virtual tresult PLUGIN_API queryInterface (const TUID _iid, void** obj) = 0; + + /** Adds a reference and return the new reference count. + \par Remarks: + The initial reference count after creating an object is 1. */ + virtual uint32 PLUGIN_API addRef () = 0; + + /** Releases a reference and return the new reference count. + If the reference count reaches zero, the object will be destroyed in memory. */ + virtual uint32 PLUGIN_API release () = 0; + +//------------------------------------------------------------------------ + static const FUID iid; +//------------------------------------------------------------------------ +}; + + +DECLARE_CLASS_IID (FUnknown, 0x00000000, 0x00000000, 0xC0000000, 0x00000046) + +//------------------------------------------------------------------------ +// FUnknownPtr +//------------------------------------------------------------------------ +/** FUnknownPtr - automatic interface conversion and smart pointer in one. + This template class can be used for interface conversion like this: + \code + IPtr path = owned (FHostCreate (IPath, hostClasses)); + FUnknownPtr path2 (path); // does a query interface for IPath2 + if (path2) + ... + \endcode +*/ +//------------------------------------------------------------------------ +template +class FUnknownPtr : public IPtr +{ +public: +//------------------------------------------------------------------------ + inline FUnknownPtr (FUnknown* unknown); // query interface + inline FUnknownPtr (const FUnknownPtr& p) : IPtr (p) {} + inline FUnknownPtr () {} + + inline FUnknownPtr& operator= (const FUnknownPtr& p) + { + IPtr::operator= (p); + return *this; + } + inline I* operator= (FUnknown* unknown); + inline I* getInterface () { return this->ptr; } +}; + +//------------------------------------------------------------------------ +template +inline FUnknownPtr::FUnknownPtr (FUnknown* unknown) +{ + if (unknown && unknown->queryInterface (I::iid, (void**)&this->ptr) != kResultOk) + this->ptr = 0; +} + +//------------------------------------------------------------------------ +template +inline I* FUnknownPtr::operator= (FUnknown* unknown) +{ + I* newPtr = 0; + if (unknown && unknown->queryInterface (I::iid, (void**)&newPtr) == kResultOk) + { + OPtr rel (newPtr); + return IPtr::operator= (newPtr); + } + + return IPtr::operator= (0); +} + +//------------------------------------------------------------------------ +// FReleaser (obsolete) +//------------------------------------------------------------------------ +/** Release an interface using automatic object (obsolete). +This class is obsolete and is only kept for compatibility. +The replacement for FReleaser is OPtr. + +Usage example with FReleaser: + \code + void someFunction () + { + IPath* path = pathCreateMethod (); + FReleaser releaser (path); + .... do something with path... + .... path not used anymore, releaser will destroy it when leaving function scope + } + \endcode +Usage example with OPtr: + \code + void someFunction () + { + OPtr path = pathCreateMethod (); + .... do something with path... + .... path not used anymore, OPtr will destroy it when leaving function scope + } + \endcode +*/ +//------------------------------------------------------------------------ +struct FReleaser +{ + FReleaser (FUnknown* u) : u (u) {} + ~FReleaser () + { + if (u) + u->release (); + } + FUnknown* u; +}; + +//------------------------------------------------------------------------ +} // namespace Steinberg diff --git a/libs/vst3/pluginterfaces/base/ibstream.h b/libs/vst3/pluginterfaces/base/ibstream.h new file mode 100644 index 0000000000..6219255014 --- /dev/null +++ b/libs/vst3/pluginterfaces/base/ibstream.h @@ -0,0 +1,89 @@ +//----------------------------------------------------------------------------- +// Project : SDK Core +// +// Category : SDK Core Interfaces +// Filename : pluginterfaces/base/ibstream.h +// Created by : Steinberg, 01/2004 +// Description : Interface for reading/writing streams +// +//----------------------------------------------------------------------------- +// This file is part of a Steinberg SDK. It is subject to the license terms +// in the LICENSE file found in the top-level directory of this distribution +// and at www.steinberg.net/sdklicenses. +// No part of the SDK, including this file, may be copied, modified, propagated, +// or distributed except according to the terms contained in the LICENSE file. +//----------------------------------------------------------------------------- + +#pragma once + +#include "funknown.h" + +namespace Steinberg { + +//------------------------------------------------------------------------ +/** Base class for streams. +\ingroup pluginBase +- read/write binary data from/to stream +- get/set stream read-write position (read and write position is the same) +*/ +//------------------------------------------------------------------------ + +class IBStream: public FUnknown +{ +public: + enum IStreamSeekMode + { + kIBSeekSet = 0, ///< set absolute seek position + kIBSeekCur, ///< set seek position relative to current position + kIBSeekEnd ///< set seek position relative to stream end + }; + +//------------------------------------------------------------------------ + /** Reads binary data from stream. + \param buffer : destination buffer + \param numBytes : amount of bytes to be read + \param numBytesRead : result - how many bytes have been read from stream (set to 0 if this is of no interest) */ + virtual tresult PLUGIN_API read (void* buffer, int32 numBytes, int32* numBytesRead = 0) = 0; + + /** Writes binary data to stream. + \param buffer : source buffer + \param numBytes : amount of bytes to write + \param numBytesWritten : result - how many bytes have been written to stream (set to 0 if this is of no interest) */ + virtual tresult PLUGIN_API write (void* buffer, int32 numBytes, int32* numBytesWritten = 0) = 0; + + /** Sets stream read-write position. + \param pos : new stream position (dependent on mode) + \param mode : value of enum IStreamSeekMode + \param result : new seek position (set to 0 if this is of no interest) */ + virtual tresult PLUGIN_API seek (int64 pos, int32 mode, int64* result = 0) = 0; + + /** Gets current stream read-write position. + \param pos : is assigned the current position if function succeeds */ + virtual tresult PLUGIN_API tell (int64* pos) = 0; +//------------------------------------------------------------------------ + static const FUID iid; +}; + +DECLARE_CLASS_IID (IBStream, 0xC3BF6EA2, 0x30994752, 0x9B6BF990, 0x1EE33E9B) + +//------------------------------------------------------------------------ +/** Stream with a size. +\ingroup pluginBase +[extends IBStream] when stream type supports it (like file and memory stream) */ +//------------------------------------------------------------------------ +class ISizeableStream: public FUnknown +{ +public: +//------------------------------------------------------------------------ + /** Return the stream size */ + virtual tresult PLUGIN_API getStreamSize (int64& size) = 0; + /** Set the steam size. File streams can only be resized if they are write enabled. */ + virtual tresult PLUGIN_API setStreamSize (int64 size) = 0; + +//------------------------------------------------------------------------ + static const FUID iid; +}; +DECLARE_CLASS_IID (ISizeableStream, 0x04F9549E, 0xE02F4E6E, 0x87E86A87, 0x47F4E17F) + +//------------------------------------------------------------------------ +} // namespace Steinberg diff --git a/libs/vst3/pluginterfaces/base/ipluginbase.h b/libs/vst3/pluginterfaces/base/ipluginbase.h new file mode 100644 index 0000000000..4370bcea06 --- /dev/null +++ b/libs/vst3/pluginterfaces/base/ipluginbase.h @@ -0,0 +1,436 @@ +//----------------------------------------------------------------------------- +// Project : SDK Core +// +// Category : SDK Core Interfaces +// Filename : pluginterfaces/base/ipluginbase.h +// Created by : Steinberg, 01/2004 +// Description : Basic Plug-in Interfaces +// +//----------------------------------------------------------------------------- +// This file is part of a Steinberg SDK. It is subject to the license terms +// in the LICENSE file found in the top-level directory of this distribution +// and at www.steinberg.net/sdklicenses. +// No part of the SDK, including this file, may be copied, modified, propagated, +// or distributed except according to the terms contained in the LICENSE file. +//----------------------------------------------------------------------------- + +#pragma once + +#include "funknown.h" +#include "fstrdefs.h" + +namespace Steinberg { + +//------------------------------------------------------------------------ +/** Basic interface to a Plug-in component. +\ingroup pluginBase +- [plug imp] +- initialize/terminate the Plug-in component + +The host uses this interface to initialize and to terminate the Plug-in component. +The context that is passed to the initialize method contains any interface to the +host that the Plug-in will need to work. These interfaces can vary from category to category. +A list of supported host context interfaces should be included in the documentation +of a specific category. */ +//------------------------------------------------------------------------ +class IPluginBase: public FUnknown +{ +public: +//------------------------------------------------------------------------ + /** The host passes a number of interfaces as context to initialize the Plug-in class. + @note Extensive memory allocations etc. should be performed in this method rather than in the class' constructor! + If the method does NOT return kResultOk, the object is released immediately. In this case terminate is not called! */ + virtual tresult PLUGIN_API initialize (FUnknown* context) = 0; + + /** This function is called before the Plug-in is unloaded and can be used for + cleanups. You have to release all references to any host application interfaces. */ + virtual tresult PLUGIN_API terminate () = 0; + +//------------------------------------------------------------------------ + static const FUID iid; +}; + +DECLARE_CLASS_IID (IPluginBase, 0x22888DDB, 0x156E45AE, 0x8358B348, 0x08190625) + + +//------------------------------------------------------------------------ +/** Basic Information about the class factory of the Plug-in. +\ingroup pluginBase +*/ +//------------------------------------------------------------------------ +struct PFactoryInfo +{ +//------------------------------------------------------------------------ + enum FactoryFlags + { + kNoFlags = 0, ///< Nothing + kClassesDiscardable = 1 << 0, ///< The number of exported classes can change each time the Module is loaded. If this flag is set, the host does not cache class information. This leads to a longer startup time because the host always has to load the Module to get the current class information. + kLicenseCheck = 1 << 1, ///< Class IDs of components are interpreted as Syncrosoft-License (LICENCE_UID). Loaded in a Steinberg host, the module will not be loaded when the license is not valid + kComponentNonDiscardable = 1 << 3, ///< Component won't be unloaded until process exit + kUnicode = 1 << 4 ///< Components have entirely unicode encoded strings. (True for VST 3 Plug-ins so far) + }; + + enum + { + kURLSize = 256, + kEmailSize = 128, + kNameSize = 64 + }; + +//------------------------------------------------------------------------ + char8 vendor[kNameSize]; ///< e.g. "Steinberg Media Technologies" + char8 url[kURLSize]; ///< e.g. "http://www.steinberg.de" + char8 email[kEmailSize]; ///< e.g. "info@steinberg.de" + int32 flags; ///< (see above) +//------------------------------------------------------------------------ + PFactoryInfo (const char8* _vendor, const char8* _url, const char8* _email, int32 _flags) + { + strncpy8 (vendor, _vendor, kNameSize); + strncpy8 (url, _url, kURLSize); + strncpy8 (email, _email, kEmailSize); + flags = _flags; +#ifdef UNICODE + flags |= kUnicode; +#endif + } +#if SMTG_CPP11 + constexpr PFactoryInfo () : vendor (), url (), email (), flags () {} +#else + PFactoryInfo () { memset (this, 0, sizeof (PFactoryInfo)); } +#endif +}; + +//------------------------------------------------------------------------ +/** Basic Information about a class provided by the Plug-in. +\ingroup pluginBase +*/ +//------------------------------------------------------------------------ +struct PClassInfo +{ +//------------------------------------------------------------------------ + enum ClassCardinality + { + kManyInstances = 0x7FFFFFFF + }; + + enum + { + kCategorySize = 32, + kNameSize = 64 + }; +//------------------------------------------------------------------------ + TUID cid; ///< Class ID 16 Byte class GUID + int32 cardinality; ///< cardinality of the class, set to kManyInstances (see \ref ClassCardinality) + char8 category[kCategorySize]; ///< class category, host uses this to categorize interfaces + char8 name[kNameSize]; ///< class name, visible to the user +//------------------------------------------------------------------------ + + PClassInfo (const TUID _cid, int32 _cardinality, const char8* _category, const char8* _name) + { + memset (this, 0, sizeof (PClassInfo)); + memcpy (cid, _cid, sizeof (TUID)); + if (_category) + strncpy8 (category, _category, kCategorySize); + if (_name) + strncpy8 (name, _name, kNameSize); + cardinality = _cardinality; + } +#if SMTG_CPP11 + constexpr PClassInfo () : cid (), cardinality (), category (), name () {} +#else + PClassInfo () { memset (this, 0, sizeof (PClassInfo)); } +#endif +}; + + +//------------------------------------------------------------------------ +// IPluginFactory interface declaration +//------------------------------------------------------------------------ +/** Class factory that any Plug-in defines for creating class instances. +\ingroup pluginBase +- [plug imp] + +From the host's point of view a Plug-in module is a factory which can create +a certain kind of object(s). The interface IPluginFactory provides methods +to get information about the classes exported by the Plug-in and a +mechanism to create instances of these classes (that usually define the IPluginBase interface). + + An implementation is provided in public.sdk/source/common/pluginfactory.cpp +\see GetPluginFactory +*/ +//------------------------------------------------------------------------ +class IPluginFactory : public FUnknown +{ +public: +//------------------------------------------------------------------------ + /** Fill a PFactoryInfo structure with information about the Plug-in vendor. */ + virtual tresult PLUGIN_API getFactoryInfo (PFactoryInfo* info) = 0; + + /** Returns the number of exported classes by this factory. + If you are using the CPluginFactory implementation provided by the SDK, it returns the number of classes you registered with CPluginFactory::registerClass. */ + virtual int32 PLUGIN_API countClasses () = 0; + + /** Fill a PClassInfo structure with information about the class at the specified index. */ + virtual tresult PLUGIN_API getClassInfo (int32 index, PClassInfo* info) = 0; + + /** Create a new class instance. */ + virtual tresult PLUGIN_API createInstance (FIDString cid, FIDString _iid, void** obj) = 0; + +//------------------------------------------------------------------------ + static const FUID iid; +}; + +DECLARE_CLASS_IID (IPluginFactory, 0x7A4D811C, 0x52114A1F, 0xAED9D2EE, 0x0B43BF9F) + + +//------------------------------------------------------------------------ +/** Version 2 of Basic Information about a class provided by the Plug-in. +\ingroup pluginBase +*/ +//------------------------------------------------------------------------ +struct PClassInfo2 +{ +//------------------------------------------------------------------------ + TUID cid; ///< Class ID 16 Byte class GUID + int32 cardinality; ///< cardinality of the class, set to kManyInstances (see \ref ClassCardinality) + char8 category[PClassInfo::kCategorySize]; ///< class category, host uses this to categorize interfaces + char8 name[PClassInfo::kNameSize]; ///< class name, visible to the user + + enum { + kVendorSize = 64, + kVersionSize = 64, + kSubCategoriesSize = 128 + }; + + uint32 classFlags; ///< flags used for a specific category, must be defined where category is defined + char8 subCategories[kSubCategoriesSize]; ///< module specific subcategories, can be more than one, logically added by the \c OR operator + char8 vendor[kVendorSize]; ///< overwrite vendor information from factory info + char8 version[kVersionSize]; ///< Version string (e.g. "1.0.0.512" with Major.Minor.Subversion.Build) + char8 sdkVersion[kVersionSize]; ///< SDK version used to build this class (e.g. "VST 3.0") + +//------------------------------------------------------------------------ + + PClassInfo2 (const TUID _cid, int32 _cardinality, const char8* _category, const char8* _name, + int32 _classFlags, const char8* _subCategories, const char8* _vendor, const char8* _version, + const char8* _sdkVersion) + { + memset (this, 0, sizeof (PClassInfo2)); + memcpy (cid, _cid, sizeof (TUID)); + cardinality = _cardinality; + if (_category) + strncpy8 (category, _category, PClassInfo::kCategorySize); + if (_name) + strncpy8 (name, _name, PClassInfo::kNameSize); + classFlags = static_cast (_classFlags); + if (_subCategories) + strncpy8 (subCategories, _subCategories, kSubCategoriesSize); + if (_vendor) + strncpy8 (vendor, _vendor, kVendorSize); + if (_version) + strncpy8 (version, _version, kVersionSize); + if (_sdkVersion) + strncpy8 (sdkVersion, _sdkVersion, kVersionSize); + } +#if SMTG_CPP11 + constexpr PClassInfo2 () + : cid () + , cardinality () + , category () + , name () + , classFlags () + , subCategories () + , vendor () + , version () + , sdkVersion () + { + } +#else + PClassInfo2 () { memset (this, 0, sizeof (PClassInfo2)); } +#endif +}; + +//------------------------------------------------------------------------ +// IPluginFactory2 interface declaration +//------------------------------------------------------------------------ +/** Version 2 of class factory supporting PClassInfo2. +\ingroup pluginBase +\copydoc IPluginFactory +*/ +//------------------------------------------------------------------------ +class IPluginFactory2 : public IPluginFactory +{ +public: +//------------------------------------------------------------------------ + /** Returns the class info (version 2) for a given index. */ + virtual tresult PLUGIN_API getClassInfo2 (int32 index, PClassInfo2* info) = 0; + +//------------------------------------------------------------------------ + static const FUID iid; +}; +DECLARE_CLASS_IID (IPluginFactory2, 0x0007B650, 0xF24B4C0B, 0xA464EDB9, 0xF00B2ABB) + + +//------------------------------------------------------------------------ +/** Unicode Version of Basic Information about a class provided by the Plug-in */ +//------------------------------------------------------------------------ +struct PClassInfoW +{ +//------------------------------------------------------------------------ + TUID cid; ///< see \ref PClassInfo + int32 cardinality; ///< see \ref PClassInfo + char8 category[PClassInfo::kCategorySize]; ///< see \ref PClassInfo + char16 name[PClassInfo::kNameSize]; ///< see \ref PClassInfo + + enum { + kVendorSize = 64, + kVersionSize = 64, + kSubCategoriesSize = 128 + }; + + uint32 classFlags; ///< flags used for a specific category, must be defined where category is defined + char8 subCategories[kSubCategoriesSize];///< module specific subcategories, can be more than one, logically added by the \c OR operator + char16 vendor[kVendorSize]; ///< overwrite vendor information from factory info + char16 version[kVersionSize]; ///< Version string (e.g. "1.0.0.512" with Major.Minor.Subversion.Build) + char16 sdkVersion[kVersionSize]; ///< SDK version used to build this class (e.g. "VST 3.0") + +//------------------------------------------------------------------------ + PClassInfoW (const TUID _cid, int32 _cardinality, const char8* _category, const char16* _name, + int32 _classFlags, const char8* _subCategories, const char16* _vendor, const char16* _version, + const char16* _sdkVersion) + { + memset (this, 0, sizeof (PClassInfoW)); + memcpy (cid, _cid, sizeof (TUID)); + cardinality = _cardinality; + if (_category) + strncpy8 (category, _category, PClassInfo::kCategorySize); + if (_name) + strncpy16 (name, _name, PClassInfo::kNameSize); + classFlags = static_cast (_classFlags); + if (_subCategories) + strncpy8 (subCategories, _subCategories, kSubCategoriesSize); + if (_vendor) + strncpy16 (vendor, _vendor, kVendorSize); + if (_version) + strncpy16 (version, _version, kVersionSize); + if (_sdkVersion) + strncpy16 (sdkVersion, _sdkVersion, kVersionSize); + } +#if SMTG_CPP11 + constexpr PClassInfoW () + : cid () + , cardinality () + , category () + , name () + , classFlags () + , subCategories () + , vendor () + , version () + , sdkVersion () + { + } +#else + PClassInfoW () { memset (this, 0, sizeof (PClassInfoW)); } +#endif + + void fromAscii (const PClassInfo2& ci2) + { + memcpy (cid, ci2.cid, sizeof (TUID)); + cardinality = ci2.cardinality; + strncpy8 (category, ci2.category, PClassInfo::kCategorySize); + str8ToStr16 (name, ci2.name, PClassInfo::kNameSize); + classFlags = ci2.classFlags; + strncpy8 (subCategories, ci2.subCategories, kSubCategoriesSize); + + str8ToStr16 (vendor, ci2.vendor, kVendorSize); + str8ToStr16 (version, ci2.version, kVersionSize); + str8ToStr16 (sdkVersion, ci2.sdkVersion, kVersionSize); + } +}; + + +//------------------------------------------------------------------------ +// IPluginFactory3 interface declaration +//------------------------------------------------------------------------ +/** Version 3 of class factory supporting PClassInfoW. +\ingroup pluginBase +\copydoc IPluginFactory +*/ +//------------------------------------------------------------------------ +class IPluginFactory3 : public IPluginFactory2 +{ +public: +//------------------------------------------------------------------------ + /** Returns the unicode class info for a given index. */ + virtual tresult PLUGIN_API getClassInfoUnicode (int32 index, PClassInfoW* info) = 0; + + /** Receives information about host*/ + virtual tresult PLUGIN_API setHostContext (FUnknown* context) = 0; + +//------------------------------------------------------------------------ + static const FUID iid; +}; +DECLARE_CLASS_IID (IPluginFactory3, 0x4555A2AB, 0xC1234E57, 0x9B122910, 0x36878931) +//------------------------------------------------------------------------ +} // namespace Steinberg + + +//------------------------------------------------------------------------ +#define LICENCE_UID(l1, l2, l3, l4) \ +{ \ + (int8)((l1 & 0xFF000000) >> 24), (int8)((l1 & 0x00FF0000) >> 16), \ + (int8)((l1 & 0x0000FF00) >> 8), (int8)((l1 & 0x000000FF) ), \ + (int8)((l2 & 0xFF000000) >> 24), (int8)((l2 & 0x00FF0000) >> 16), \ + (int8)((l2 & 0x0000FF00) >> 8), (int8)((l2 & 0x000000FF) ), \ + (int8)((l3 & 0xFF000000) >> 24), (int8)((l3 & 0x00FF0000) >> 16), \ + (int8)((l3 & 0x0000FF00) >> 8), (int8)((l3 & 0x000000FF) ), \ + (int8)((l4 & 0xFF000000) >> 24), (int8)((l4 & 0x00FF0000) >> 16), \ + (int8)((l4 & 0x0000FF00) >> 8), (int8)((l4 & 0x000000FF) ) \ +} + + +//------------------------------------------------------------------------ +// GetPluginFactory +//------------------------------------------------------------------------ +/** Plug-in entry point. +\ingroup pluginBase +Any Plug-in must define and export this function. \n +A typical implementation of GetPluginFactory looks like this + \code + IPluginFactory* PLUGIN_API GetPluginFactory () + { + if (!gPluginFactory) + { + static PFactoryInfo factoryInfo = + { + "My Company Name", + "http://www.mywebpage.com", + "mailto:myemail@address.com", + PFactoryInfo::kNoFlags + }; + + gPluginFactory = new CPluginFactory (factoryInfo); + + static PClassInfo componentClass = + { + INLINE_UID (0x00000000, 0x00000000, 0x00000000, 0x00000000), // replace by a valid uid + 1, + "Service", // category + "Name" + }; + + gPluginFactory->registerClass (&componentClass, MyComponentClass::newInstance); + } + else + gPluginFactory->addRef (); + + return gPluginFactory; + } + \endcode +\see \ref loadPlugin +*/ +//------------------------------------------------------------------------ +extern "C" +{ + Steinberg::IPluginFactory* PLUGIN_API GetPluginFactory (); + typedef Steinberg::IPluginFactory* (PLUGIN_API *GetFactoryProc) (); +} diff --git a/libs/vst3/pluginterfaces/base/istringresult.h b/libs/vst3/pluginterfaces/base/istringresult.h new file mode 100644 index 0000000000..90531838cd --- /dev/null +++ b/libs/vst3/pluginterfaces/base/istringresult.h @@ -0,0 +1,80 @@ +//----------------------------------------------------------------------------- +// Project : SDK Core +// +// Category : SDK Core Interfaces +// Filename : pluginterfaces/base/istringresult.h +// Created by : Steinberg, 01/2005 +// Description : Strings Interface +// +//----------------------------------------------------------------------------- +// This file is part of a Steinberg SDK. It is subject to the license terms +// in the LICENSE file found in the top-level directory of this distribution +// and at www.steinberg.net/sdklicenses. +// No part of the SDK, including this file, may be copied, modified, propagated, +// or distributed except according to the terms contained in the LICENSE file. +//----------------------------------------------------------------------------- + +#pragma once + +#include "pluginterfaces/base/funknown.h" + +namespace Steinberg { + +//------------------------------------------------------------------------ +/** Interface to return an ascii string of variable size. + In order to manage memory allocation and deallocation properly, + this interface is used to transfer a string as result parameter of + a method requires a string of unknown size. +[host imp] or [plug imp] \n +[released: SX 4] */ +//------------------------------------------------------------------------ +class IStringResult : public FUnknown +{ +public: +//------------------------------------------------------------------------ + virtual void PLUGIN_API setText (const char8* text) = 0; + +//------------------------------------------------------------------------ + static const FUID iid; +}; + +DECLARE_CLASS_IID (IStringResult, 0x550798BC, 0x872049DB, 0x84920A15, 0x3B50B7A8) + + +//------------------------------------------------------------------------ +/** Interface to a string of variable size and encoding. +[host imp] or [plug imp] \n +[released: ] */ +//------------------------------------------------------------------------ +class IString : public FUnknown +{ +public: +//------------------------------------------------------------------------ + /** Assign ASCII string */ + virtual void PLUGIN_API setText8 (const char8* text) = 0; + /** Assign unicode string */ + virtual void PLUGIN_API setText16 (const char16* text) = 0; + + /** Return ASCII string. If the string is unicode so far, it will be converted. + So you need to be careful, because the conversion can result in data loss. + It is save though to call getText8 if isWideString() returns false */ + virtual const char8* PLUGIN_API getText8 () = 0; + /** Return unicode string. If the string is ASCII so far, it will be converted. */ + virtual const char16* PLUGIN_API getText16 () = 0; + + /** !Do not use this method! Early implementations take the given pointer as + internal string and this will cause problems because 'free' will be used to delete the passed memory. + Later implementations will redirect 'take' to setText8 and setText16 */ + virtual void PLUGIN_API take (void* s, bool isWide) = 0; + + /** Returns true if the string is in unicode format, returns false if the string is ASCII */ + virtual bool PLUGIN_API isWideString () const = 0; + +//------------------------------------------------------------------------ + static const FUID iid; +}; + +DECLARE_CLASS_IID (IString, 0xF99DB7A3, 0x0FC14821, 0x800B0CF9, 0x8E348EDF) + +//------------------------------------------------------------------------ +} // namespace Steinberg diff --git a/libs/vst3/pluginterfaces/base/smartpointer.h b/libs/vst3/pluginterfaces/base/smartpointer.h new file mode 100644 index 0000000000..f9af78be1d --- /dev/null +++ b/libs/vst3/pluginterfaces/base/smartpointer.h @@ -0,0 +1,386 @@ +//----------------------------------------------------------------------------- +// Project : SDK Core +// +// Category : SDK Core Interfaces +// Filename : pluginterfaces/base/smartpointer.h +// Created by : Steinberg, 01/2004 +// Description : Basic Interface +// +//----------------------------------------------------------------------------- +// This file is part of a Steinberg SDK. It is subject to the license terms +// in the LICENSE file found in the top-level directory of this distribution +// and at www.steinberg.net/sdklicenses. +// No part of the SDK, including this file, may be copied, modified, propagated, +// or distributed except according to the terms contained in the LICENSE file. +//----------------------------------------------------------------------------- + +#pragma once + +#include "pluginterfaces/base/fplatform.h" +#if SMTG_CPP11_STDLIBSUPPORT +#include +#endif + +//------------------------------------------------------------------------ +namespace Steinberg { + +//------------------------------------------------------------------------ +// IPtr +//------------------------------------------------------------------------ +/** IPtr - Smart pointer template class. + \ingroup pluginBase + + - can be used as an I* pointer + - handles refCount of the interface + - Usage example: + \code + IPtr path (sharedPath); + if (path) + path->ascend (); + \endcode + */ +//------------------------------------------------------------------------ +template +class IPtr +{ +public: +//------------------------------------------------------------------------ + inline IPtr (I* ptr, bool addRef = true); + inline IPtr (const IPtr&); + + template + inline IPtr (const IPtr& other) : ptr (other.get ()) + { + if (ptr) + ptr->addRef (); + } + + inline IPtr (); + inline ~IPtr (); + + inline I* operator= (I* ptr); + + inline IPtr& operator= (const IPtr& other); + + template + inline IPtr& operator= (const IPtr& other) + { + operator= (other.get ()); + return *this; + } + + inline operator I* () const { return ptr; } // act as I* + inline I* operator-> () const { return ptr; } // act as I* + + inline I* get () const { return ptr; } + +#if SMTG_CPP11_STDLIBSUPPORT + inline IPtr (IPtr&& movePtr) SMTG_NOEXCEPT : ptr (movePtr.take ()) { } + + template + inline IPtr (IPtr&& movePtr) SMTG_NOEXCEPT : ptr (movePtr.take ()) { } + + inline IPtr& operator= (IPtr&& movePtr) + { + if (ptr) + ptr->release (); + + ptr = movePtr.take (); + return *this; + } + + template + inline IPtr& operator= (IPtr&& movePtr) + { + if (ptr) + ptr->release (); + + ptr = movePtr.take (); + return *this; + } + + inline void reset (I* obj = nullptr) + { + if (ptr) + ptr->release(); + ptr = obj; + } + + I* take () SMTG_NOEXCEPT + { + I* out = ptr; + ptr = nullptr; + return out; + } + + template + static IPtr adopt (T* obj) SMTG_NOEXCEPT { return IPtr (obj, false); } + +#endif +//------------------------------------------------------------------------ +protected: + I* ptr; +}; + +//------------------------------------------------------------------------ +template +inline IPtr::IPtr (I* _ptr, bool addRef) : ptr (_ptr) +{ + if (ptr && addRef) + ptr->addRef (); +} + +//------------------------------------------------------------------------ +template +inline IPtr::IPtr (const IPtr& other) : ptr (other.ptr) +{ + if (ptr) + ptr->addRef (); +} + +//------------------------------------------------------------------------ +template +inline IPtr::IPtr () : ptr (0) +{ +} + +//------------------------------------------------------------------------ +template +inline IPtr::~IPtr () +{ + if (ptr) + { + ptr->release (); + ptr = nullptr; //TODO_CORE: how much does this cost? is this something hiding for us? + } +} + +//------------------------------------------------------------------------ +template +inline I* IPtr::operator= (I* _ptr) +{ + if (_ptr != ptr) + { + if (ptr) + ptr->release (); + ptr = _ptr; + if (ptr) + ptr->addRef (); + } + return ptr; +} + +//------------------------------------------------------------------------ +template +inline IPtr& IPtr::operator= (const IPtr& _ptr) +{ + operator= (_ptr.ptr); + return *this; +} + +//------------------------------------------------------------------------ +/** OPtr - "owning" smart pointer used for newly created FObjects. + \ingroup pluginBase + + FUnknown implementations are supposed to have a refCount of 1 right after creation. + So using an IPtr on newly created objects would lead to a leak. + Instead the OPtr can be used in this case. \n + Example: + \code + OPtr path = FHostCreate (IPath, hostClasses); + // no release is needed... + \endcode + The assignment operator takes ownership of a new object and releases the old. + So its safe to write: + \code + OPtr path = FHostCreate (IPath, hostClasses); + path = FHostCreate (IPath, hostClasses); + path = 0; + \endcode + This is the difference to using an IPtr with addRef=false. + \code + // DONT DO THIS: + IPtr path (FHostCreate (IPath, hostClasses), false); + path = FHostCreate (IPath, hostClasses); + path = 0; + \endcode + This will lead to a leak! + */ +//------------------------------------------------------------------------ +template +class OPtr : public IPtr +{ +public: +//------------------------------------------------------------------------ + inline OPtr (I* p) : IPtr (p, false) {} + inline OPtr (const IPtr& p) : IPtr (p) {} + inline OPtr (const OPtr& p) : IPtr (p) {} + inline OPtr () {} + inline I* operator= (I* _ptr) + { + if (_ptr != this->ptr) + { + if (this->ptr) + this->ptr->release (); + this->ptr = _ptr; + } + return this->ptr; + } +}; + +//------------------------------------------------------------------------ +/** Assigning newly created object to an IPtr. + Example: + \code + IPtr path = owned (FHostCreate (IPath, hostClasses)); + \endcode + which is a slightly shorter form of writing: + \code + IPtr path = OPtr (FHostCreate (IPath, hostClasses)); + \endcode + */ +template +IPtr owned (I* p) +{ + return IPtr (p, false); +} + +/** Assigning shared object to an IPtr. + Example: + \code + IPtr path = shared (iface.getXY ()); + \endcode + */ +template +IPtr shared (I* p) +{ + return IPtr (p, true); +} + +#if SMTG_CPP11_STDLIBSUPPORT +//------------------------------------------------------------------------ +// Ownership functionality +//------------------------------------------------------------------------ +namespace SKI { +namespace Detail { +struct Adopt; +} // Detail + +/** Strong typedef for shared reference counted objects. + * Use SKI::adopt to unwrap the provided object. + * @tparam T Referenced counted type. + */ +template +class Shared +{ + friend struct Detail::Adopt; + T* obj = nullptr; +}; + +/** Strong typedef for transferring the ownership of reference counted objects. + * Use SKI::adopt to unwrap the provided object. + * After calling adopt the reference in this object is null. + * @tparam T Referenced counted type. + */ +template +class Owned +{ + friend struct Detail::Adopt; + T* obj = nullptr; +}; + +/** Strong typedef for using reference counted objects. + * Use SKI::adopt to unwrap the provided object. + * After calling adopt the reference in this object is null. + * @tparam T Referenced counted type. + */ +template +class Used +{ + friend struct Detail::Adopt; + T* obj = nullptr; +}; + +namespace Detail { + +struct Adopt +{ + template + static IPtr adopt (Shared& ref) + { + using Steinberg::shared; + return shared (ref.obj); + } + + template + static IPtr adopt (Owned& ref) + { + using Steinberg::owned; + IPtr out = owned (ref.obj); + ref.obj = nullptr; + return out; + } + + template + static T* adopt (Used& ref) + { + return ref.obj; + } + + template