1 /*
2  * PluginManager.h
3  * ---------------
4  * Purpose: Plugin management
5  * Notes  : (currently none)
6  * Authors: OpenMPT Devs
7  * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
8  */
9 
10 
11 #pragma once
12 
13 #include "openmpt/all/BuildSettings.hpp"
14 
15 OPENMPT_NAMESPACE_BEGIN
16 
PLUGMAGIC(char a,char b,char c,char d)17 constexpr int32 PLUGMAGIC(char a, char b, char c, char d) noexcept
18 {
19 	return static_cast<int32>((static_cast<uint32>(a) << 24) | (static_cast<uint32>(b) << 16) | (static_cast<uint32>(c) << 8) | (static_cast<uint32>(d) << 0));
20 }
21 
22 //#define kBuzzMagic	PLUGMAGIC('B', 'u', 'z', 'z')
23 inline constexpr int32 kDmoMagic = PLUGMAGIC('D', 'X', 'M', 'O');
24 
25 class CSoundFile;
26 class IMixPlugin;
27 struct SNDMIXPLUGIN;
28 enum PluginArch : int;
29 
30 struct VSTPluginLib
31 {
32 public:
33 	enum PluginCategory : uint8
34 	{
35 		// Same plugin categories as defined in VST SDK
36 		catUnknown = 0,
37 		catEffect,          // Simple Effect
38 		catSynth,           // VST Instrument (Synths, samplers,...)
39 		catAnalysis,        // Scope, Tuner, ...
40 		catMastering,       // Dynamics, ...
41 		catSpacializer,     // Panners, ...
42 		catRoomFx,          // Delays and Reverbs
43 		catSurroundFx,      // Dedicated surround processor
44 		catRestoration,     // Denoiser, ...
45 		catOfflineProcess,  // Offline Process
46 		catShell,           // Plug-in is container of other plug-ins
47 		catGenerator,       // Tone Generator, ...
48 		// Custom categories
49 		catDMO,     // DirectX media object plugin
50 		catHidden,  // For internal plugins that should not be visible to the user (e.g. because they only exist for legacy reasons)
51 
52 		numCategories
53 	};
54 
55 public:
56 	using CreateProc = IMixPlugin *(*)(VSTPluginLib &factory, CSoundFile &sndFile, SNDMIXPLUGIN *mixStruct);
57 
58 	IMixPlugin *pPluginsList = nullptr; // Pointer to first plugin instance (this instance carries pointers to other instances)
59 	CreateProc Create;                  // Factory to call for this plugin
60 	mpt::PathString libraryName;        // Display name
61 	mpt::PathString dllPath;            // Full path name
62 #ifdef MODPLUG_TRACKER
63 	mpt::ustring tags;                  // User tags
64 	CString vendor;
65 #endif // MODPLUG_TRACKER
66 	int32 pluginId1 = 0;                // Plugin type (kEffectMagic, kDmoMagic, ...)
67 	int32 pluginId2 = 0;                // Plugin unique ID
68 	PluginCategory category = catUnknown;
69 	const bool isBuiltIn : 1;
70 	bool isInstrument : 1;
71 	bool useBridge : 1, shareBridgeInstance : 1, modernBridge : 1;
72 protected:
73 	mutable uint8 dllArch = 0;
74 
75 public:
76 	VSTPluginLib(CreateProc factoryProc, bool isBuiltIn, const mpt::PathString &dllPath, const mpt::PathString &libraryName
77 #ifdef MODPLUG_TRACKER
78 		, const mpt::ustring &tags = mpt::ustring(), const CString &vendor = CString()
79 #endif // MODPLUG_TRACKER
80 		)
CreateVSTPluginLib81 		: Create(factoryProc)
82 		, libraryName(libraryName), dllPath(dllPath)
83 #ifdef MODPLUG_TRACKER
84 		, tags(tags)
85 		, vendor(vendor)
86 #endif // MODPLUG_TRACKER
87 		, category(catUnknown)
88 		, isBuiltIn(isBuiltIn), isInstrument(false)
89 		, useBridge(false), shareBridgeInstance(true), modernBridge(true)
90 	{
91 	}
92 
93 #ifdef MPT_WITH_VST
94 
95 	// Get native phost process arch encoded as plugin arch
96 	static uint8 GetNativePluginArch();
97 	static mpt::ustring GetPluginArchName(uint8 arch);
98 	static mpt::ustring GetPluginArchNameUser(uint8 arch);
99 
100 	// Check whether a plugin can be hosted inside OpenMPT or requires bridging
101 	uint8 GetDllArch(bool fromCache = true) const;
102 	mpt::ustring GetDllArchName(bool fromCache = true) const;
103 	mpt::ustring GetDllArchNameUser(bool fromCache = true) const;
104 	bool IsNative(bool fromCache = true) const;
105 	// Check if a plugin is native, and if it is currently unknown, assume that it is native. Use this function only for performance reasons
106 	// (e.g. if tons of unscanned plugins would slow down generation of the plugin selection dialog)
107 	bool IsNativeFromCache() const;
108 
109 #endif // MPT_WITH_VST
110 
111 	void WriteToCache() const;
112 
EncodeCacheFlagsVSTPluginLib113 	uint32 EncodeCacheFlags() const
114 	{
115 		// Format: 00000000.0000000M.AAAAAASB.CCCCCCCI
116 		return (isInstrument ? 1 : 0)
117 			| (category << 1)
118 			| (useBridge ? 0x100 : 0)
119 			| (shareBridgeInstance ? 0x200 : 0)
120 			| ((dllArch / 8) << 10)
121 			| (modernBridge ? 0x10000 : 0)
122 			;
123 	}
124 
DecodeCacheFlagsVSTPluginLib125 	void DecodeCacheFlags(uint32 flags)
126 	{
127 		category = static_cast<PluginCategory>((flags & 0xFF) >> 1);
128 		if(category >= numCategories)
129 		{
130 			category = catUnknown;
131 		}
132 		if(flags & 1)
133 		{
134 			isInstrument = true;
135 			category = catSynth;
136 		}
137 		useBridge = (flags & 0x100) != 0;
138 		shareBridgeInstance = (flags & 0x200) != 0;
139 		dllArch = ((flags >> 10) & 0x3F) * 8;
140 		modernBridge = (flags & 0x10000) != 0;
141 	}
142 };
143 
144 
145 class CVstPluginManager
146 {
147 #ifndef NO_PLUGINS
148 protected:
149 #if defined(MPT_WITH_DMO)
150 	bool MustUnInitilizeCOM = false;
151 #endif
152 	std::vector<VSTPluginLib *> pluginList;
153 
154 public:
155 	CVstPluginManager();
156 	~CVstPluginManager();
157 
158 	using iterator = std::vector<VSTPluginLib *>::iterator;
159 	using const_iterator = std::vector<VSTPluginLib *>::const_iterator;
160 
begin()161 	iterator begin() { return pluginList.begin(); }
begin()162 	const_iterator begin() const { return pluginList.begin(); }
end()163 	iterator end() { return pluginList.end(); }
end()164 	const_iterator end() const { return pluginList.end(); }
reserve(size_t num)165 	void reserve(size_t num) { pluginList.reserve(num); }
size()166 	size_t size() const { return pluginList.size(); }
167 
168 	bool IsValidPlugin(const VSTPluginLib *pLib) const;
169 	VSTPluginLib *AddPlugin(const mpt::PathString &dllPath, bool maskCrashes, const mpt::ustring &tags = mpt::ustring(), bool fromCache = true, bool *fileFound = nullptr);
170 	bool RemovePlugin(VSTPluginLib *);
171 	bool CreateMixPlugin(SNDMIXPLUGIN &, CSoundFile &);
172 	void OnIdle();
173 	static void ReportPlugException(const mpt::ustring &msg);
174 
175 protected:
176 	void EnumerateDirectXDMOs();
177 
178 #else // NO_PLUGINS
179 public:
180 	const VSTPluginLib **begin() const { return nullptr; }
181 	const VSTPluginLib **end() const { return nullptr; }
182 	void reserve(size_t) { }
183 	size_t size() const { return 0; }
184 
185 	void OnIdle() {}
186 #endif // NO_PLUGINS
187 };
188 
189 
190 OPENMPT_NAMESPACE_END
191