Initial release
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Project : SDK Core
|
||||
// Version : 1.0
|
||||
//
|
||||
// Category : Common Base Classes
|
||||
// Filename : public.sdk/source/main/dllmain.cpp
|
||||
// Created by : Steinberg, 01/2004
|
||||
// Description : Windows DLL Entry
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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 "pluginterfaces/base/ftypes.h"
|
||||
#include "pluginterfaces/base/fstrdefs.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#if defined(_MSC_VER) && defined(DEVELOPMENT)
|
||||
#include <crtdbg.h>
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
HINSTANCE ghInst = nullptr;
|
||||
void* moduleHandle = nullptr;
|
||||
#define VST_MAX_PATH 2048
|
||||
Steinberg::tchar gPath[VST_MAX_PATH] = {0};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
extern bool InitModule (); ///< must be provided by plug-in: called when the library is loaded
|
||||
extern bool DeinitModule (); ///< must be provided by plug-in: called when the library is unloaded
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static int moduleCounter {0}; // counting for InitDll/ExitDll pairs
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
/** must be called from host right after loading dll,
|
||||
must be provided by the plug-in!
|
||||
Note: this could be called more than one time! */
|
||||
SMTG_EXPORT_SYMBOL bool InitDll ()
|
||||
{
|
||||
if (++moduleCounter == 1)
|
||||
return InitModule ();
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
/** must be called from host right before unloading dll
|
||||
must be provided by the plug-in!
|
||||
Note: this could be called more than one time! */
|
||||
SMTG_EXPORT_SYMBOL bool ExitDll ()
|
||||
{
|
||||
if (--moduleCounter == 0)
|
||||
return DeinitModule ();
|
||||
if (moduleCounter < 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
BOOL WINAPI DllMain (HINSTANCE hInst, DWORD dwReason, LPVOID /*lpvReserved*/)
|
||||
{
|
||||
if (dwReason == DLL_PROCESS_ATTACH)
|
||||
{
|
||||
#if defined(_MSC_VER) && defined(DEVELOPMENT)
|
||||
_CrtSetReportMode (_CRT_WARN, _CRTDBG_MODE_DEBUG);
|
||||
_CrtSetReportMode (_CRT_ERROR, _CRTDBG_MODE_DEBUG);
|
||||
_CrtSetReportMode (_CRT_ASSERT, _CRTDBG_MODE_DEBUG);
|
||||
int flag = _CrtSetDbgFlag (_CRTDBG_REPORT_FLAG);
|
||||
_CrtSetDbgFlag (flag | _CRTDBG_LEAK_CHECK_DF);
|
||||
#endif
|
||||
|
||||
moduleHandle = ghInst = hInst;
|
||||
|
||||
// gets the path of the component
|
||||
if (GetModuleFileName (ghInst, Steinberg::wscast (gPath), MAX_PATH) > 0)
|
||||
{
|
||||
Steinberg::tchar* bkslash = Steinberg::wscast (wcsrchr (Steinberg::wscast (gPath), L'\\'));
|
||||
if (bkslash)
|
||||
gPath[bkslash - gPath + 1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Project : SDK Core
|
||||
// Version : 1.0
|
||||
//
|
||||
// Category : Common Base Classes
|
||||
// Filename : public.sdk/source/main/linuxmain.cpp
|
||||
// Created by : Steinberg, 03/2017
|
||||
// Description : Linux Component Entry
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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 "pluginterfaces/base/fplatform.h"
|
||||
|
||||
void* moduleHandle = nullptr;
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
bool InitModule (); ///< must be provided by plug-in: called when the library is loaded
|
||||
bool DeinitModule (); ///< must be provided by plug-in: called when the library is unloaded
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
extern "C"
|
||||
{
|
||||
/** must be provided by the plug-in! */
|
||||
SMTG_EXPORT_SYMBOL bool ModuleEntry (void*);
|
||||
SMTG_EXPORT_SYMBOL bool ModuleExit (void);
|
||||
}
|
||||
|
||||
static int moduleCounter {0}; // counting for ModuleEntry/ModuleExit pairs
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
/** must be called from host right after loading dll
|
||||
Note: this could be called more than one time! */
|
||||
bool ModuleEntry (void* sharedLibraryHandle)
|
||||
{
|
||||
if (++moduleCounter == 1)
|
||||
{
|
||||
moduleHandle = sharedLibraryHandle;
|
||||
return InitModule ();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
/** must be called from host right before unloading dll
|
||||
Note: this could be called more than one time! */
|
||||
bool ModuleExit (void)
|
||||
{
|
||||
if (--moduleCounter == 0)
|
||||
{
|
||||
moduleHandle = nullptr;
|
||||
return DeinitModule ();
|
||||
}
|
||||
else if (moduleCounter < 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Project : SDK Core
|
||||
// Version : 1.0
|
||||
//
|
||||
// Category : Common Base Classes
|
||||
// Filename : public.sdk/source/main/macmain.cpp
|
||||
// Created by : Steinberg, 01/2004
|
||||
// Description : Mac OS X Bundle Entry
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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 "pluginterfaces/base/fplatform.h"
|
||||
|
||||
#ifndef __CF_USE_FRAMEWORK_INCLUDES__
|
||||
#define __CF_USE_FRAMEWORK_INCLUDES__ 1
|
||||
#endif
|
||||
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
CFBundleRef ghInst = nullptr;
|
||||
int bundleRefCounter = 0; // counting for bundleEntry/bundleExit pairs
|
||||
void* moduleHandle = nullptr;
|
||||
#define VST_MAX_PATH 2048
|
||||
char gPath[VST_MAX_PATH] = {0};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
bool InitModule (); ///< must be provided by plug-in: called when the library is loaded
|
||||
bool DeinitModule (); ///< must be provided by plug-in: called when the library is unloaded
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
extern "C" {
|
||||
/** bundleEntry and bundleExit must be provided by the plug-in! */
|
||||
SMTG_EXPORT_SYMBOL bool bundleEntry (CFBundleRef);
|
||||
SMTG_EXPORT_SYMBOL bool bundleExit (void);
|
||||
}
|
||||
|
||||
#include <vector>
|
||||
|
||||
std::vector<CFBundleRef> gBundleRefs;
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
/** must be called from host right after loading bundle
|
||||
Note: this could be called more than one time! */
|
||||
bool bundleEntry (CFBundleRef ref)
|
||||
{
|
||||
if (ref)
|
||||
{
|
||||
bundleRefCounter++;
|
||||
CFRetain (ref);
|
||||
|
||||
// hold all bundle refs until plug-in is fully uninitialized
|
||||
gBundleRefs.push_back (ref);
|
||||
|
||||
if (!moduleHandle)
|
||||
{
|
||||
ghInst = ref;
|
||||
moduleHandle = ref;
|
||||
|
||||
// obtain the bundle path
|
||||
CFURLRef tempURL = CFBundleCopyBundleURL (ref);
|
||||
CFURLGetFileSystemRepresentation (tempURL, true, reinterpret_cast<UInt8*> (gPath), VST_MAX_PATH);
|
||||
CFRelease (tempURL);
|
||||
}
|
||||
|
||||
if (bundleRefCounter == 1)
|
||||
return InitModule ();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
/** must be called from host right before unloading bundle
|
||||
Note: this could be called more than one time! */
|
||||
bool bundleExit (void)
|
||||
{
|
||||
if (--bundleRefCounter == 0)
|
||||
{
|
||||
DeinitModule ();
|
||||
|
||||
// release the CFBundleRef's once all bundleExit clients called in
|
||||
// there is no way to identify the proper CFBundleRef of the bundleExit call
|
||||
for (size_t i = 0; i < gBundleRefs.size (); i++)
|
||||
CFRelease (gBundleRefs[i]);
|
||||
gBundleRefs.clear ();
|
||||
}
|
||||
else if (bundleRefCounter < 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Project : SDK Core
|
||||
//
|
||||
// Category : Common Base Classes
|
||||
// Filename : public.sdk/source/main/moduleinit.cpp
|
||||
// Created by : Steinberg, 11/2020
|
||||
// Description : Module Initializers/Terminators
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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 "moduleinit.h"
|
||||
#include <atomic>
|
||||
#include <vector>
|
||||
|
||||
extern void* moduleHandle; // from dllmain.cpp, linuxmain.cpp or macmain.cpp
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
namespace Steinberg {
|
||||
namespace {
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
using FunctionVector = std::vector<std::pair<ModuleInitPriority, ModuleInitFunction>>;
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
FunctionVector& getInitFunctions ()
|
||||
{
|
||||
static FunctionVector gInitVector;
|
||||
return gInitVector;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
FunctionVector& getTermFunctions ()
|
||||
{
|
||||
static FunctionVector gTermVector;
|
||||
return gTermVector;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void addInitFunction (ModuleInitFunction&& func, ModuleInitPriority prio)
|
||||
{
|
||||
getInitFunctions ().emplace_back (prio, std::move (func));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void addTerminateFunction (ModuleInitFunction&& func, ModuleInitPriority prio)
|
||||
{
|
||||
getTermFunctions ().emplace_back (prio, std::move (func));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void sortAndRunFunctions (FunctionVector& array)
|
||||
{
|
||||
std::sort (array.begin (), array.end (),
|
||||
[] (const FunctionVector::value_type& v1, const FunctionVector::value_type& v2) {
|
||||
return v1.first < v2.first;
|
||||
});
|
||||
for (auto& entry : array)
|
||||
entry.second ();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
} // anonymous
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
ModuleInitializer::ModuleInitializer (ModuleInitFunction&& func, ModuleInitPriority prio)
|
||||
{
|
||||
addInitFunction (std::move (func), prio);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
ModuleTerminator::ModuleTerminator (ModuleInitFunction&& func, ModuleInitPriority prio)
|
||||
{
|
||||
addTerminateFunction (std::move (func), prio);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
PlatformModuleHandle getPlatformModuleHandle ()
|
||||
{
|
||||
return reinterpret_cast<PlatformModuleHandle> (moduleHandle);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
} // Steinberg
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
bool InitModule ()
|
||||
{
|
||||
Steinberg::sortAndRunFunctions (Steinberg::getInitFunctions ());
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
bool DeinitModule ()
|
||||
{
|
||||
Steinberg::sortAndRunFunctions (Steinberg::getTermFunctions ());
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Project : SDK Core
|
||||
//
|
||||
// Category : Common Base Classes
|
||||
// Filename : public.sdk/source/main/moduleinit.h
|
||||
// Created by : Steinberg, 11/2020
|
||||
// Description : Module Initializers/Terminators
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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/ftypes.h"
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
#include <numeric>
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
/** A replacement for InitModule and DeinitModule
|
||||
*
|
||||
* If you link this file the InitModule and DeinitModule functions are
|
||||
* implemented and you can use this to register functions that will be
|
||||
* called when the module is loaded and before the module is unloaded.
|
||||
*
|
||||
* Use this for one time initializers or cleanup functions.
|
||||
* For example: if you depend on a 3rd party library that needs
|
||||
* initialization before you can use it you can write an initializer like this:
|
||||
*
|
||||
* static ModuleInitializer InitMyExternalLib ([] () { MyExternalLib::init (); });
|
||||
*
|
||||
* Or you have a lazy create wavetable you need to free the allocated memory later:
|
||||
*
|
||||
* static ModuleTerminator FreeWaveTableMemory ([] () { MyWaveTable::free (); });
|
||||
*/
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
#if SMTG_OS_WINDOWS
|
||||
using HINSTANCE = struct HINSTANCE__*;
|
||||
namespace Steinberg { using PlatformModuleHandle = HINSTANCE; }
|
||||
//------------------------------------------------------------------------
|
||||
#elif SMTG_OS_OSX || SMTG_OS_IOS
|
||||
typedef struct __CFBundle* CFBundleRef;
|
||||
namespace Steinberg { using PlatformModuleHandle = CFBundleRef; }
|
||||
//------------------------------------------------------------------------
|
||||
#elif SMTG_OS_LINUX
|
||||
namespace Steinberg { using PlatformModuleHandle = void*; }
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
namespace Steinberg {
|
||||
|
||||
using ModuleInitFunction = std::function<void ()>;
|
||||
using ModuleInitPriority = uint32;
|
||||
static constexpr ModuleInitPriority DefaultModulePriority =
|
||||
std::numeric_limits<ModuleInitPriority>::max () / 2;
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
struct ModuleInitializer
|
||||
{
|
||||
/**
|
||||
* Register a function which is called when the module is loaded
|
||||
* @param func function to call
|
||||
* @param prio priority
|
||||
*/
|
||||
ModuleInitializer (ModuleInitFunction&& func,
|
||||
ModuleInitPriority prio = DefaultModulePriority);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
struct ModuleTerminator
|
||||
{
|
||||
/**
|
||||
* Register a function which is called when the module is unloaded
|
||||
* @param func function to call
|
||||
* @param prio priority
|
||||
*/
|
||||
ModuleTerminator (ModuleInitFunction&& func,
|
||||
ModuleInitPriority prio = DefaultModulePriority);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
PlatformModuleHandle getPlatformModuleHandle ();
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
} // Steinberg
|
||||
|
||||
@@ -0,0 +1,340 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Project : SDK Core
|
||||
//
|
||||
// Category : Common Base Classes
|
||||
// Filename : public.sdk/source/main/pluginfactory.cpp
|
||||
// Created by : Steinberg, 01/2004
|
||||
// Description : Standard Plug-In Factory
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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 "pluginfactory.h"
|
||||
|
||||
#if SMTG_OS_LINUX
|
||||
#include "pluginterfaces/base/funknownimpl.h"
|
||||
#include "pluginterfaces/gui/iplugview.h"
|
||||
#include "base/source/timer.h"
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
|
||||
namespace Steinberg {
|
||||
|
||||
DEF_CLASS_IID (IPluginFactoryInternal);
|
||||
|
||||
CPluginFactory* gPluginFactory = nullptr;
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// CPluginFactory implementation
|
||||
//------------------------------------------------------------------------
|
||||
CPluginFactory::CPluginFactory (const PFactoryInfo& info)
|
||||
: classes (nullptr), classCount (0), maxClassCount (0)
|
||||
{
|
||||
FUNKNOWN_CTOR
|
||||
|
||||
factoryInfo = info;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
CPluginFactory::~CPluginFactory ()
|
||||
{
|
||||
if (gPluginFactory == this)
|
||||
gPluginFactory = nullptr;
|
||||
|
||||
if (classes)
|
||||
free (classes);
|
||||
|
||||
FUNKNOWN_DTOR
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
IMPLEMENT_REFCOUNT (CPluginFactory)
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
tresult PLUGIN_API CPluginFactory::queryInterface (FIDString _iid, void** obj)
|
||||
{
|
||||
QUERY_INTERFACE (_iid, obj, IPluginFactory::iid, IPluginFactory)
|
||||
QUERY_INTERFACE (_iid, obj, IPluginFactory2::iid, IPluginFactory2)
|
||||
QUERY_INTERFACE (_iid, obj, IPluginFactory3::iid, IPluginFactory3)
|
||||
QUERY_INTERFACE (_iid, obj, IPluginFactoryInternal::iid, IPluginFactoryInternal)
|
||||
QUERY_INTERFACE (_iid, obj, FUnknown::iid, IPluginFactory)
|
||||
*obj = nullptr;
|
||||
return kNoInterface;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
bool CPluginFactory::registerClass (const PClassInfo* info, FUnknown* (*createFunc) (void*),
|
||||
void* context)
|
||||
{
|
||||
if (!info || !createFunc)
|
||||
return false;
|
||||
|
||||
PClassInfo2 info2;
|
||||
memcpy (&info2, info, sizeof (PClassInfo));
|
||||
return registerClass (&info2, createFunc, context);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
bool CPluginFactory::registerClass (const PClassInfo2* info, FUnknown* (*createFunc) (void*),
|
||||
void* context)
|
||||
{
|
||||
if (!info || !createFunc)
|
||||
return false;
|
||||
|
||||
if (classCount >= maxClassCount)
|
||||
{
|
||||
if (!growClasses ())
|
||||
return false;
|
||||
}
|
||||
|
||||
PClassEntry& entry = classes[classCount];
|
||||
entry.info8 = *info;
|
||||
entry.info16.fromAscii (*info);
|
||||
entry.createFunc = createFunc;
|
||||
entry.context = context;
|
||||
entry.isUnicode = false;
|
||||
|
||||
classCount++;
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
bool CPluginFactory::registerClass (const PClassInfoW* info, FUnknown* (*createFunc) (void*),
|
||||
void* context)
|
||||
{
|
||||
if (!info || !createFunc)
|
||||
return false;
|
||||
|
||||
if (classCount >= maxClassCount)
|
||||
{
|
||||
if (!growClasses ())
|
||||
return false;
|
||||
}
|
||||
|
||||
PClassEntry& entry = classes[classCount];
|
||||
entry.info16 = *info;
|
||||
entry.createFunc = createFunc;
|
||||
entry.context = context;
|
||||
entry.isUnicode = true;
|
||||
|
||||
classCount++;
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
bool CPluginFactory::growClasses ()
|
||||
{
|
||||
static const int32 delta = 10;
|
||||
|
||||
size_t size = (maxClassCount + delta) * sizeof (PClassEntry);
|
||||
void* memory = classes;
|
||||
|
||||
if (!memory)
|
||||
memory = malloc (size);
|
||||
else
|
||||
memory = realloc (memory, size);
|
||||
|
||||
if (!memory)
|
||||
return false;
|
||||
|
||||
classes = static_cast<PClassEntry*> (memory);
|
||||
maxClassCount += delta;
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
bool CPluginFactory::isClassRegistered (const FUID& cid)
|
||||
{
|
||||
for (int32 i = 0; i < classCount; i++)
|
||||
{
|
||||
if (FUnknownPrivate::iidEqual (cid, classes[i].info16.cid))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void CPluginFactory::removeAllClasses ()
|
||||
{
|
||||
classCount = 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
tresult PLUGIN_API CPluginFactory::getFactoryInfo (PFactoryInfo* info)
|
||||
{
|
||||
if (info)
|
||||
memcpy (info, &factoryInfo, sizeof (PFactoryInfo));
|
||||
return kResultOk;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
int32 PLUGIN_API CPluginFactory::countClasses ()
|
||||
{
|
||||
return classCount;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
tresult PLUGIN_API CPluginFactory::getClassInfo (int32 index, PClassInfo* info)
|
||||
{
|
||||
if (info && (index >= 0 && index < classCount))
|
||||
{
|
||||
if (classes[index].isUnicode)
|
||||
{
|
||||
memset (info, 0, sizeof (PClassInfo));
|
||||
return kResultFalse;
|
||||
}
|
||||
|
||||
memcpy (info, &classes[index].info8, sizeof (PClassInfo));
|
||||
return kResultOk;
|
||||
}
|
||||
return kInvalidArgument;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
tresult PLUGIN_API CPluginFactory::getClassInfo2 (int32 index, PClassInfo2* info)
|
||||
{
|
||||
if (info && (index >= 0 && index < classCount))
|
||||
{
|
||||
if (classes[index].isUnicode)
|
||||
{
|
||||
memset (info, 0, sizeof (PClassInfo2));
|
||||
return kResultFalse;
|
||||
}
|
||||
|
||||
memcpy (info, &classes[index].info8, sizeof (PClassInfo2));
|
||||
return kResultOk;
|
||||
}
|
||||
return kInvalidArgument;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
tresult PLUGIN_API CPluginFactory::getClassInfoUnicode (int32 index, PClassInfoW* info)
|
||||
{
|
||||
if (info && (index >= 0 && index < classCount))
|
||||
{
|
||||
memcpy (info, &classes[index].info16, sizeof (PClassInfoW));
|
||||
return kResultOk;
|
||||
}
|
||||
return kInvalidArgument;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
tresult PLUGIN_API CPluginFactory::createInstance (FIDString cid, FIDString _iid, void** obj)
|
||||
{
|
||||
for (int32 i = 0; i < classCount; i++)
|
||||
{
|
||||
if (memcmp (classes[i].info16.cid, cid, sizeof (TUID)) == 0)
|
||||
{
|
||||
FUnknown* instance = classes[i].createFunc (classes[i].context);
|
||||
if (instance)
|
||||
{
|
||||
if (instance->queryInterface (_iid, obj) == kResultOk)
|
||||
{
|
||||
instance->release ();
|
||||
return kResultOk;
|
||||
}
|
||||
instance->release ();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*obj = nullptr;
|
||||
return kNoInterface;
|
||||
}
|
||||
|
||||
#if SMTG_OS_LINUX
|
||||
//------------------------------------------------------------------------
|
||||
namespace /*anonymous*/ {
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
class LinuxPlatformTimer : public U::Extends<Timer, U::Directly<Linux::ITimerHandler>>
|
||||
{
|
||||
public:
|
||||
~LinuxPlatformTimer () noexcept override { stop (); }
|
||||
|
||||
tresult init (ITimerCallback* cb, uint32 timeout)
|
||||
{
|
||||
if (!runLoop || cb == nullptr || timeout == 0)
|
||||
return kResultFalse;
|
||||
auto result = runLoop->registerTimer (this, timeout);
|
||||
if (result == kResultTrue)
|
||||
{
|
||||
callback = cb;
|
||||
timerRegistered = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void PLUGIN_API onTimer () override { callback->onTimer (this); }
|
||||
|
||||
void stop () override
|
||||
{
|
||||
if (timerRegistered)
|
||||
{
|
||||
if (runLoop)
|
||||
runLoop->unregisterTimer (this);
|
||||
timerRegistered = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool timerRegistered {false};
|
||||
ITimerCallback* callback;
|
||||
|
||||
static IPtr<Linux::IRunLoop> runLoop;
|
||||
};
|
||||
IPtr<Linux::IRunLoop> LinuxPlatformTimer::runLoop;
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
Timer* createLinuxTimer (ITimerCallback* cb, uint32 milliseconds)
|
||||
{
|
||||
if (!LinuxPlatformTimer::runLoop)
|
||||
return nullptr;
|
||||
auto timer = NEW LinuxPlatformTimer;
|
||||
if (timer->init (cb, milliseconds) == kResultTrue)
|
||||
return timer;
|
||||
timer->release ();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // anonymous
|
||||
#endif // SMTG_OS_LINUX
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
tresult PLUGIN_API CPluginFactory::setHostContext (FUnknown* context)
|
||||
{
|
||||
std::for_each (hostContextCallbacks.begin (), hostContextCallbacks.end (),
|
||||
[context] (const auto& cb) { cb (context); });
|
||||
#if SMTG_OS_LINUX
|
||||
if (auto runLoop = U::cast<Linux::IRunLoop> (context))
|
||||
{
|
||||
LinuxPlatformTimer::runLoop = runLoop;
|
||||
InjectCreateTimerFunction (createLinuxTimer);
|
||||
}
|
||||
else
|
||||
{
|
||||
LinuxPlatformTimer::runLoop.reset ();
|
||||
InjectCreateTimerFunction (nullptr);
|
||||
}
|
||||
return kResultTrue;
|
||||
#else
|
||||
(void) context;
|
||||
return kNotImplemented;
|
||||
#endif
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void PLUGIN_API CPluginFactory::addHostContextCallback (HostContextCallbackFunc func)
|
||||
{
|
||||
hostContextCallbacks.push_back (func);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
} // namespace Steinberg
|
||||
@@ -0,0 +1,191 @@
|
||||
//------------------------------------------------------------------------
|
||||
// Project : SDK Core
|
||||
//
|
||||
// Category : Common Base Classes
|
||||
// Filename : public.sdk/source/main/pluginfactory.h
|
||||
// Created by : Steinberg, 01/2004
|
||||
// Description : Standard Plug-In Factory
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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/ipluginbase.h"
|
||||
#include <vector>
|
||||
|
||||
namespace Steinberg {
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
class IPluginFactoryInternal : public FUnknown
|
||||
{
|
||||
public:
|
||||
using HostContextCallbackFunc = void (*) (FUnknown*);
|
||||
virtual void PLUGIN_API addHostContextCallback (HostContextCallbackFunc func) = 0;
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
static const FUID iid;
|
||||
};
|
||||
DECLARE_CLASS_IID (IPluginFactoryInternal, 0x5A6AD11A, 0x22AF40F3, 0xBCA1C147, 0x506C88D9)
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
/** Default Class Factory implementation.
|
||||
\ingroup sdkBase
|
||||
\see classFactoryMacros
|
||||
*/
|
||||
class CPluginFactory : public IPluginFactory3, public IPluginFactoryInternal
|
||||
{
|
||||
public:
|
||||
//------------------------------------------------------------------------
|
||||
CPluginFactory (const PFactoryInfo& info);
|
||||
virtual ~CPluginFactory ();
|
||||
|
||||
//--- ---------------------------------------------------------------------
|
||||
/** Registers a plug-in class with classInfo version 1, returns true for success. */
|
||||
bool registerClass (const PClassInfo* info, FUnknown* (*createFunc) (void*),
|
||||
void* context = nullptr);
|
||||
|
||||
/** Registers a plug-in class with classInfo version 2, returns true for success. */
|
||||
bool registerClass (const PClassInfo2* info, FUnknown* (*createFunc) (void*),
|
||||
void* context = nullptr);
|
||||
|
||||
/** Registers a plug-in class with classInfo Unicode version, returns true for success. */
|
||||
bool registerClass (const PClassInfoW* info, FUnknown* (*createFunc) (void*),
|
||||
void* context = nullptr);
|
||||
|
||||
/** Check if a class for a given classId is already registered. */
|
||||
bool isClassRegistered (const FUID& cid);
|
||||
|
||||
/** Remove all classes (no class exported) */
|
||||
void removeAllClasses ();
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
DECLARE_FUNKNOWN_METHODS
|
||||
|
||||
//---from IPluginFactory------
|
||||
tresult PLUGIN_API getFactoryInfo (PFactoryInfo* info) SMTG_OVERRIDE;
|
||||
int32 PLUGIN_API countClasses () SMTG_OVERRIDE;
|
||||
tresult PLUGIN_API getClassInfo (int32 index, PClassInfo* info) SMTG_OVERRIDE;
|
||||
tresult PLUGIN_API createInstance (FIDString cid, FIDString _iid, void** obj) SMTG_OVERRIDE;
|
||||
|
||||
//---from IPluginFactory2-----
|
||||
tresult PLUGIN_API getClassInfo2 (int32 index, PClassInfo2* info) SMTG_OVERRIDE;
|
||||
|
||||
//---from IPluginFactory3-----
|
||||
tresult PLUGIN_API getClassInfoUnicode (int32 index, PClassInfoW* info) SMTG_OVERRIDE;
|
||||
tresult PLUGIN_API setHostContext (FUnknown* context) SMTG_OVERRIDE;
|
||||
|
||||
//---from IPluginFactoryInternal
|
||||
void PLUGIN_API addHostContextCallback (HostContextCallbackFunc func) SMTG_OVERRIDE;
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
protected:
|
||||
/// @cond
|
||||
struct PClassEntry
|
||||
{
|
||||
//-----------------------------------
|
||||
PClassInfo2 info8;
|
||||
PClassInfoW info16;
|
||||
|
||||
FUnknown* (*createFunc) (void*);
|
||||
void* context;
|
||||
bool isUnicode;
|
||||
//-----------------------------------
|
||||
};
|
||||
/// @endcond
|
||||
|
||||
PFactoryInfo factoryInfo;
|
||||
PClassEntry* classes;
|
||||
int32 classCount;
|
||||
int32 maxClassCount;
|
||||
|
||||
std::vector<HostContextCallbackFunc> hostContextCallbacks;
|
||||
|
||||
bool growClasses ();
|
||||
};
|
||||
|
||||
extern CPluginFactory* gPluginFactory;
|
||||
//------------------------------------------------------------------------
|
||||
} // namespace Steinberg
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
/** \defgroup classFactoryMacros Macros for defining the class factory
|
||||
\ingroup sdkBase
|
||||
|
||||
\b Example - How to use the class factory macros:
|
||||
\code
|
||||
BEGIN_FACTORY ("Steinberg Technologies",
|
||||
"http://www.steinberg.de",
|
||||
"mailto:info@steinberg.de",
|
||||
PFactoryInfo::kNoFlags)
|
||||
|
||||
DEF_CLASS (INLINE_UID (0x00000000, 0x00000000, 0x00000000, 0x00000000),
|
||||
PClassInfo::kManyInstances,
|
||||
"Service",
|
||||
"Test Service",
|
||||
TestService::newInstance)
|
||||
END_FACTORY
|
||||
\endcode
|
||||
|
||||
@{*/
|
||||
|
||||
#define BEGIN_FACTORY_CLASS(FactoryClass,vendor,url,email,flags) using namespace Steinberg; \
|
||||
SMTG_EXPORT_SYMBOL IPluginFactory* PLUGIN_API GetPluginFactory () { \
|
||||
if (!gPluginFactory) \
|
||||
{ static PFactoryInfo factoryInfo (vendor,url,email,flags); \
|
||||
gPluginFactory = new FactoryClass (factoryInfo); \
|
||||
|
||||
#define BEGIN_FACTORY(vendor,url,email,flags) using namespace Steinberg; \
|
||||
SMTG_EXPORT_SYMBOL IPluginFactory* PLUGIN_API GetPluginFactory () { \
|
||||
if (!gPluginFactory) \
|
||||
{ static PFactoryInfo factoryInfo (vendor,url,email,flags); \
|
||||
gPluginFactory = new CPluginFactory (factoryInfo); \
|
||||
|
||||
#define DEF_CLASS(cid,cardinality,category,name,createMethod) \
|
||||
{ TUID lcid = cid; static PClassInfo componentClass (lcid,cardinality,category,name); \
|
||||
gPluginFactory->registerClass (&componentClass,createMethod); }
|
||||
|
||||
#define DEF_CLASS1(cid,cardinality,category,name,createMethod) \
|
||||
{ static PClassInfo componentClass (cid,cardinality,category,name); \
|
||||
gPluginFactory->registerClass (&componentClass,createMethod); }
|
||||
|
||||
#define DEF_CLASS2(cid,cardinality,category,name,classFlags,subCategories,version,sdkVersion,createMethod) \
|
||||
{ TUID lcid = cid; static PClassInfo2 componentClass (lcid,cardinality,category,name,classFlags,subCategories,nullptr,version,sdkVersion);\
|
||||
gPluginFactory->registerClass (&componentClass,createMethod); }
|
||||
|
||||
#define DEF_CLASS_W(cid,cardinality,category,name,classFlags,subCategories,version,sdkVersion,createMethod) \
|
||||
{ TUID lcid = cid; static PClassInfoW componentClass (lcid,cardinality,category,name,classFlags,subCategories,nullptr,version,sdkVersion);\
|
||||
gPluginFactory->registerClass (&componentClass,createMethod); }
|
||||
|
||||
#define DEF_CLASS_W2(cid,cardinality,category,name,classFlags,subCategories,vendor,version,sdkVersion,createMethod) \
|
||||
{ TUID lcid = cid; static PClassInfoW componentClass (lcid,cardinality,category,name,classFlags,subCategories,vendor,version,sdkVersion);\
|
||||
gPluginFactory->registerClass (&componentClass,createMethod); }
|
||||
|
||||
#define END_FACTORY } else gPluginFactory->addRef (); \
|
||||
return gPluginFactory; }
|
||||
|
||||
#define DEF_VST3_CLASS(pluginName, pluginVst3Categories, classFlags, pluginVersion, processorCID, \
|
||||
processorCreateFunc, controllerCID, controllerCreateFunc) \
|
||||
{ \
|
||||
{ \
|
||||
const Steinberg::TUID lcid = processorCID; \
|
||||
static Steinberg::PClassInfo2 processorClass ( \
|
||||
lcid, Steinberg::PClassInfo::kManyInstances, kVstAudioEffectClass, pluginName, \
|
||||
classFlags, pluginVst3Categories, 0, pluginVersion, kVstVersionString); \
|
||||
gPluginFactory->registerClass (&processorClass, processorCreateFunc); \
|
||||
} \
|
||||
{ \
|
||||
const Steinberg::TUID lcid = controllerCID; \
|
||||
static Steinberg::PClassInfo2 controllerClass ( \
|
||||
lcid, Steinberg::PClassInfo::kManyInstances, kVstComponentControllerClass, \
|
||||
pluginName, 0, "", 0, pluginVersion, kVstVersionString); \
|
||||
gPluginFactory->registerClass (&controllerClass, controllerCreateFunc); \
|
||||
} \
|
||||
}
|
||||
|
||||
/** @} */
|
||||
@@ -0,0 +1,201 @@
|
||||
//------------------------------------------------------------------------
|
||||
// Flags : clang-format SMTGSequencer
|
||||
// Project : SDK Core
|
||||
//
|
||||
// Category : Common Base Classes
|
||||
// Filename : public.sdk/source/main/pluginfactory_constexpr.h
|
||||
// Created by : Steinberg, 10/2021
|
||||
// Description : Standard Plug-In Factory (constexpr variant)
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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/funknownimpl.h"
|
||||
#include "pluginterfaces/base/ipluginbase.h"
|
||||
|
||||
#if !SMTG_CPP17
|
||||
#error "C++17 is required for this header"
|
||||
#endif
|
||||
|
||||
#include <array>
|
||||
|
||||
namespace Steinberg {
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
/** IPluginFactory implementation with compile time provided factory and class infos.
|
||||
\ingroup sdkBase
|
||||
\see \ref constexprClassFactoryMacros
|
||||
|
||||
You can use this factory when your number of classes are known during compile time. The
|
||||
advantage here is that during runtime no unnecessary setup is needed.
|
||||
|
||||
Please note that this only supports ASCII names and thus if you need to support Unicode names
|
||||
you must use another implementation.
|
||||
|
||||
This only works when compiling with c++17 or newer.
|
||||
*/
|
||||
template <typename T>
|
||||
class PluginFactory
|
||||
: public U::ImplementsNonDestroyable<U::Directly<IPluginFactory2>, U::Indirectly<IPluginFactory>>
|
||||
{
|
||||
public:
|
||||
//------------------------------------------------------------------------
|
||||
tresult PLUGIN_API getFactoryInfo (PFactoryInfo* info) override
|
||||
{
|
||||
if (info == nullptr)
|
||||
return kInvalidArgument;
|
||||
*info = T::factoryInfo;
|
||||
return kResultTrue;
|
||||
}
|
||||
int32 PLUGIN_API countClasses () override { return static_cast<int32> (T::classInfos.size ()); }
|
||||
tresult PLUGIN_API getClassInfo (int32 index, PClassInfo* info) override
|
||||
{
|
||||
if (index < 0 || index >= static_cast<int32> (T::classInfos.size ()) || info == nullptr)
|
||||
return kInvalidArgument;
|
||||
*info = {};
|
||||
const auto& ci = T::classInfos[index];
|
||||
copyTUID (info->cid, ci.cid);
|
||||
info->cardinality = ci.cardinality;
|
||||
if (ci.category)
|
||||
strncpy (info->category, ci.category, PClassInfo::kCategorySize);
|
||||
if (ci.name)
|
||||
strncpy (info->name, ci.name, PClassInfo::kNameSize);
|
||||
return kResultTrue;
|
||||
}
|
||||
tresult PLUGIN_API createInstance (FIDString cid, FIDString iid, void** obj) override
|
||||
{
|
||||
for (const auto& e : T::classInfos)
|
||||
{
|
||||
if (FUnknownPrivate::iidEqual (e.cid, cid))
|
||||
{
|
||||
if (auto instance = e.create (e.context))
|
||||
{
|
||||
if (instance->queryInterface (iid, obj) == kResultOk)
|
||||
{
|
||||
instance->release ();
|
||||
return kResultOk;
|
||||
}
|
||||
else
|
||||
instance->release ();
|
||||
}
|
||||
}
|
||||
}
|
||||
*obj = nullptr;
|
||||
return kNoInterface;
|
||||
}
|
||||
tresult PLUGIN_API getClassInfo2 (int32 index, PClassInfo2* info) override
|
||||
{
|
||||
if (index < 0 || index >= static_cast<int32> (T::classInfos.size ()) || info == nullptr)
|
||||
return kInvalidArgument;
|
||||
*info = T::classInfos[index];
|
||||
return kResultTrue;
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
namespace PluginFactoryDetail {
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
struct ClassInfo2WithCreateFunc : PClassInfo2
|
||||
{
|
||||
using CreateInstanceFunc = FUnknown* (*)(void*);
|
||||
CreateInstanceFunc create {nullptr};
|
||||
void* context {nullptr};
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline constexpr ClassInfo2WithCreateFunc makeClassInfo2 (
|
||||
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,
|
||||
ClassInfo2WithCreateFunc::CreateInstanceFunc func, void* context = nullptr)
|
||||
{
|
||||
ClassInfo2WithCreateFunc classInfo {};
|
||||
copyTUID (classInfo.cid, cid);
|
||||
classInfo.cardinality = cardinality;
|
||||
strncpy8 (classInfo.category, category, PClassInfo::kCategorySize);
|
||||
strncpy8 (classInfo.name, name, PClassInfo::kNameSize);
|
||||
classInfo.classFlags = classFlags;
|
||||
if (subCategories)
|
||||
strncpy8 (classInfo.subCategories, subCategories, PClassInfo2::kSubCategoriesSize);
|
||||
if (vendor)
|
||||
strncpy8 (classInfo.vendor, vendor, PClassInfo2::kVendorSize);
|
||||
if (version)
|
||||
strncpy8 (classInfo.version, version, PClassInfo2::kVersionSize);
|
||||
if (sdkVersion)
|
||||
strncpy8 (classInfo.sdkVersion, sdkVersion, PClassInfo2::kVersionSize);
|
||||
classInfo.create = func;
|
||||
classInfo.context = context;
|
||||
return classInfo;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
} // namespace PluginFactoryDetail
|
||||
} // namespace Steinberg
|
||||
|
||||
#ifdef BEGIN_FACTORY_DEF
|
||||
#undef BEGIN_FACTORY_DEF
|
||||
#endif
|
||||
|
||||
/** \defgroup constexprClassFactoryMacros Macros for defining the compile time class factory
|
||||
\ingroup sdkBase
|
||||
|
||||
\b Example:
|
||||
|
||||
\code
|
||||
|
||||
static constexpr size_t numberOfClasses = 1;
|
||||
static DECLARE_UID (TestPluginUID, 0x00000001, 0x00000002, 0x00000003, 0x00000004);
|
||||
|
||||
BEGIN_FACTORY_DEF ("MyCompany", "mycompany.com", "info@mycompany.com", numberOfClasses)
|
||||
|
||||
DEF_CLASS (TestPluginUID,
|
||||
PClassInfo::kManyInstances,
|
||||
"PlugIn",
|
||||
"Test PlugIn",
|
||||
0,
|
||||
"SubCategory",
|
||||
"1.0.0",
|
||||
stringSDKVersion,
|
||||
TestPlugin::newInstance,
|
||||
nullptr)
|
||||
|
||||
END_FACTORY
|
||||
|
||||
\endcode
|
||||
|
||||
@{*/
|
||||
|
||||
// clang-format off
|
||||
#define BEGIN_FACTORY_DEF(company, url, email, noClasses) \
|
||||
struct SMTG_HIDDEN_SYMBOL FactoryData \
|
||||
{ \
|
||||
static constexpr Steinberg::PFactoryInfo factoryInfo = { \
|
||||
company, url, email, Steinberg::PFactoryInfo::kUnicode}; \
|
||||
\
|
||||
static constexpr std::array<Steinberg::PluginFactoryDetail::ClassInfo2WithCreateFunc, \
|
||||
noClasses> \
|
||||
classInfos = {
|
||||
|
||||
#define DEF_CLASS(cid, cardinality, category, name, classFlags, subCategories, version, \
|
||||
sdkVersion, createMethod, createContext) \
|
||||
Steinberg::PluginFactoryDetail::makeClassInfo2 (cid, cardinality, category, name, classFlags, \
|
||||
subCategories, nullptr, version, sdkVersion, \
|
||||
createMethod, createContext),
|
||||
|
||||
#define END_FACTORY \
|
||||
};}; \
|
||||
SMTG_EXPORT_SYMBOL Steinberg::IPluginFactory* PLUGIN_API GetPluginFactory () \
|
||||
{ \
|
||||
static Steinberg::PluginFactory<FactoryData> factory; \
|
||||
return &factory; \
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
/** @} */
|
||||
Reference in New Issue
Block a user