1 //-----------------------------------------------------------------------------
2 // Project     : SDK Core
3 //
4 // Category    : SDK Core Interfaces
5 // Filename    : pluginterfaces/base/ipluginbase.h
6 // Created by  : Steinberg, 01/2004
7 // Description : Basic Plug-in Interfaces
8 //
9 //-----------------------------------------------------------------------------
10 // This file is part of a Steinberg SDK. It is subject to the license terms
11 // in the LICENSE file found in the top-level directory of this distribution
12 // and at www.steinberg.net/sdklicenses.
13 // No part of the SDK, including this file, may be copied, modified, propagated,
14 // or distributed except according to the terms contained in the LICENSE file.
15 //-----------------------------------------------------------------------------
16 
17 #pragma once
18 
19 #include "funknown.h"
20 #include "fstrdefs.h"
21 
22 namespace Steinberg {
23 
24 //------------------------------------------------------------------------
25 /**  Basic interface to a Plug-in component.
26 \ingroup pluginBase
27 - [plug imp]
28 - initialize/terminate the Plug-in component
29 
30 The host uses this interface to initialize and to terminate the Plug-in component.
31 The context that is passed to the initialize method contains any interface to the
32 host that the Plug-in will need to work. These interfaces can vary from category to category.
33 A list of supported host context interfaces should be included in the documentation
34 of a specific category. */
35 //------------------------------------------------------------------------
36 class IPluginBase: public FUnknown
37 {
38 public:
39 //------------------------------------------------------------------------
40 	/** The host passes a number of interfaces as context to initialize the Plug-in class.
41 		@note Extensive memory allocations etc. should be performed in this method rather than in the class' constructor!
42 		If the method does NOT return kResultOk, the object is released immediately. In this case terminate is not called! */
43 	virtual tresult PLUGIN_API initialize (FUnknown* context) = 0;
44 
45 	/** This function is called before the Plug-in is unloaded and can be used for
46 	    cleanups. You have to release all references to any host application interfaces. */
47 	virtual tresult PLUGIN_API terminate () = 0;
48 
49 //------------------------------------------------------------------------
50 	static const FUID iid;
51 };
52 
53 DECLARE_CLASS_IID (IPluginBase, 0x22888DDB, 0x156E45AE, 0x8358B348, 0x08190625)
54 
55 
56 //------------------------------------------------------------------------
57 /** Basic Information about the class factory of the Plug-in.
58 \ingroup pluginBase
59 */
60 //------------------------------------------------------------------------
61 struct PFactoryInfo
62 {
63 //------------------------------------------------------------------------
64 	enum FactoryFlags
65 	{
66 		kNoFlags					= 0,		///< Nothing
67 		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.
68 		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
69 		kComponentNonDiscardable	= 1 << 3,	///< Component won't be unloaded until process exit
70 		kUnicode                    = 1 << 4    ///< Components have entirely unicode encoded strings. (True for VST 3 Plug-ins so far)
71 	};
72 
73 	enum
74 	{
75 		kURLSize = 256,
76 		kEmailSize = 128,
77 		kNameSize = 64
78 	};
79 
80 //------------------------------------------------------------------------
81 	char8 vendor[kNameSize];		///< e.g. "Steinberg Media Technologies"
82 	char8 url[kURLSize];			///< e.g. "http://www.steinberg.de"
83 	char8 email[kEmailSize];		///< e.g. "info@steinberg.de"
84 	int32 flags;				///< (see above)
85 //------------------------------------------------------------------------
PFactoryInfoPFactoryInfo86 	PFactoryInfo (const char8* _vendor, const char8* _url, const char8* _email, int32 _flags)
87 	{
88 		strncpy8 (vendor, _vendor, kNameSize);
89 		strncpy8 (url, _url, kURLSize);
90 		strncpy8 (email, _email, kEmailSize);
91 		flags = _flags;
92 #ifdef UNICODE
93 		flags |= kUnicode;
94 #endif
95 	}
96 #if SMTG_CPP11
PFactoryInfoPFactoryInfo97 	constexpr PFactoryInfo () : vendor (), url (), email (), flags () {}
98 #else
PFactoryInfoPFactoryInfo99 	PFactoryInfo () { memset (this, 0, sizeof (PFactoryInfo)); }
100 #endif
101 };
102 
103 //------------------------------------------------------------------------
104 /**  Basic Information about a class provided by the Plug-in.
105 \ingroup pluginBase
106 */
107 //------------------------------------------------------------------------
108 struct PClassInfo
109 {
110 //------------------------------------------------------------------------
111 	enum ClassCardinality
112 	{
113 		kManyInstances = 0x7FFFFFFF
114 	};
115 
116 	enum
117 	{
118 		kCategorySize = 32,
119 		kNameSize = 64
120 	};
121 //------------------------------------------------------------------------
122 	TUID cid;                       ///< Class ID 16 Byte class GUID
123 	int32 cardinality;              ///< cardinality of the class, set to kManyInstances (see \ref ClassCardinality)
124 	char8 category[kCategorySize];  ///< class category, host uses this to categorize interfaces
125 	char8 name[kNameSize];          ///< class name, visible to the user
126 //------------------------------------------------------------------------
127 
PClassInfoPClassInfo128 	PClassInfo (const TUID _cid, int32 _cardinality, const char8* _category, const char8* _name)
129 	{
130 		memset (this, 0, sizeof (PClassInfo));
131 		memcpy (cid, _cid, sizeof (TUID));
132 		if (_category)
133 			strncpy8 (category, _category, kCategorySize);
134 		if (_name)
135 			strncpy8 (name, _name, kNameSize);
136 		cardinality = _cardinality;
137 	}
138 #if SMTG_CPP11
PClassInfoPClassInfo139 	constexpr PClassInfo () : cid (), cardinality (), category (), name () {}
140 #else
PClassInfoPClassInfo141 	PClassInfo () { memset (this, 0, sizeof (PClassInfo)); }
142 #endif
143 };
144 
145 
146 //------------------------------------------------------------------------
147 //  IPluginFactory interface declaration
148 //------------------------------------------------------------------------
149 /**	Class factory that any Plug-in defines for creating class instances.
150 \ingroup pluginBase
151 - [plug imp]
152 
153 From the host's point of view a Plug-in module is a factory which can create
154 a certain kind of object(s). The interface IPluginFactory provides methods
155 to get information about the classes exported by the Plug-in and a
156 mechanism to create instances of these classes (that usually define the IPluginBase interface).
157 
158 <b> An implementation is provided in public.sdk/source/common/pluginfactory.cpp </b>
159 \see GetPluginFactory
160 */
161 //------------------------------------------------------------------------
162 class IPluginFactory : public FUnknown
163 {
164 public:
165 //------------------------------------------------------------------------
166 	/** Fill a PFactoryInfo structure with information about the Plug-in vendor. */
167 	virtual tresult PLUGIN_API getFactoryInfo (PFactoryInfo* info) = 0;
168 
169 	/** Returns the number of exported classes by this factory.
170 	If you are using the CPluginFactory implementation provided by the SDK, it returns the number of classes you registered with CPluginFactory::registerClass. */
171 	virtual int32 PLUGIN_API countClasses () = 0;
172 
173 	/** Fill a PClassInfo structure with information about the class at the specified index. */
174 	virtual tresult PLUGIN_API getClassInfo (int32 index, PClassInfo* info) = 0;
175 
176 	/** Create a new class instance. */
177 	virtual tresult PLUGIN_API createInstance (FIDString cid, FIDString _iid, void** obj) = 0;
178 
179 //------------------------------------------------------------------------
180 	static const FUID iid;
181 };
182 
183 DECLARE_CLASS_IID (IPluginFactory, 0x7A4D811C, 0x52114A1F, 0xAED9D2EE, 0x0B43BF9F)
184 
185 
186 //------------------------------------------------------------------------
187 /**  Version 2 of Basic Information about a class provided by the Plug-in.
188 \ingroup pluginBase
189 */
190 //------------------------------------------------------------------------
191 struct PClassInfo2
192 {
193 //------------------------------------------------------------------------
194 	TUID cid;									///< Class ID 16 Byte class GUID
195 	int32 cardinality;							///< cardinality of the class, set to kManyInstances (see \ref ClassCardinality)
196 	char8 category[PClassInfo::kCategorySize];	///< class category, host uses this to categorize interfaces
197 	char8 name[PClassInfo::kNameSize];			///< class name, visible to the user
198 
199 	enum {
200 		kVendorSize = 64,
201 		kVersionSize = 64,
202 		kSubCategoriesSize = 128
203 	};
204 
205 	uint32 classFlags;				///< flags used for a specific category, must be defined where category is defined
206 	char8 subCategories[kSubCategoriesSize];	///< module specific subcategories, can be more than one, logically added by the \c OR operator
207 	char8 vendor[kVendorSize];		///< overwrite vendor information from factory info
208 	char8 version[kVersionSize];	///< Version string (e.g. "1.0.0.512" with Major.Minor.Subversion.Build)
209 	char8 sdkVersion[kVersionSize];	///< SDK version used to build this class (e.g. "VST 3.0")
210 
211 //------------------------------------------------------------------------
212 
PClassInfo2PClassInfo2213 	PClassInfo2 (const TUID _cid, int32 _cardinality, const char8* _category, const char8* _name,
214 		int32 _classFlags, const char8* _subCategories, const char8* _vendor, const char8* _version,
215 		const char8* _sdkVersion)
216 	{
217 		memset (this, 0, sizeof (PClassInfo2));
218 		memcpy (cid, _cid, sizeof (TUID));
219 		cardinality = _cardinality;
220 		if (_category)
221 			strncpy8 (category, _category, PClassInfo::kCategorySize);
222 		if (_name)
223 			strncpy8 (name, _name, PClassInfo::kNameSize);
224 		classFlags = static_cast<uint32> (_classFlags);
225 		if (_subCategories)
226 			strncpy8 (subCategories, _subCategories, kSubCategoriesSize);
227 		if (_vendor)
228 			strncpy8 (vendor, _vendor, kVendorSize);
229 		if (_version)
230 			strncpy8 (version, _version, kVersionSize);
231 		if (_sdkVersion)
232 			strncpy8 (sdkVersion, _sdkVersion, kVersionSize);
233 	}
234 #if SMTG_CPP11
PClassInfo2PClassInfo2235 	constexpr PClassInfo2 ()
236 	: cid ()
237 	, cardinality ()
238 	, category ()
239 	, name ()
240 	, classFlags ()
241 	, subCategories ()
242 	, vendor ()
243 	, version ()
244 	, sdkVersion ()
245 	{
246 	}
247 #else
PClassInfo2PClassInfo2248 	PClassInfo2 () { memset (this, 0, sizeof (PClassInfo2)); }
249 #endif
250 };
251 
252 //------------------------------------------------------------------------
253 //  IPluginFactory2 interface declaration
254 //------------------------------------------------------------------------
255 /**	Version 2 of class factory supporting PClassInfo2.
256 \ingroup pluginBase
257 \copydoc IPluginFactory
258 */
259 //------------------------------------------------------------------------
260 class IPluginFactory2 : public IPluginFactory
261 {
262 public:
263 //------------------------------------------------------------------------
264 	/** Returns the class info (version 2) for a given index. */
265 	virtual tresult PLUGIN_API getClassInfo2 (int32 index, PClassInfo2* info) = 0;
266 
267 //------------------------------------------------------------------------
268 	static const FUID iid;
269 };
270 DECLARE_CLASS_IID (IPluginFactory2, 0x0007B650, 0xF24B4C0B, 0xA464EDB9, 0xF00B2ABB)
271 
272 
273 //------------------------------------------------------------------------
274 /** Unicode Version of Basic Information about a class provided by the Plug-in */
275 //------------------------------------------------------------------------
276 struct PClassInfoW
277 {
278 //------------------------------------------------------------------------
279 	TUID cid;							///< see \ref PClassInfo
280 	int32 cardinality;					///< see \ref PClassInfo
281 	char8 category[PClassInfo::kCategorySize];	///< see \ref PClassInfo
282 	char16 name[PClassInfo::kNameSize];	///< see \ref PClassInfo
283 
284 	enum {
285 		kVendorSize = 64,
286 		kVersionSize = 64,
287 		kSubCategoriesSize = 128
288 	};
289 
290 	uint32 classFlags;					///< flags used for a specific category, must be defined where category is defined
291 	char8 subCategories[kSubCategoriesSize];///< module specific subcategories, can be more than one, logically added by the \c OR operator
292 	char16 vendor[kVendorSize];			///< overwrite vendor information from factory info
293 	char16 version[kVersionSize];		///< Version string (e.g. "1.0.0.512" with Major.Minor.Subversion.Build)
294 	char16 sdkVersion[kVersionSize];	///< SDK version used to build this class (e.g. "VST 3.0")
295 
296 //------------------------------------------------------------------------
PClassInfoWPClassInfoW297 	PClassInfoW (const TUID _cid, int32 _cardinality, const char8* _category, const char16* _name,
298 		int32 _classFlags, const char8* _subCategories, const char16* _vendor, const char16* _version,
299 		const char16* _sdkVersion)
300 	{
301 		memset (this, 0, sizeof (PClassInfoW));
302 		memcpy (cid, _cid, sizeof (TUID));
303 		cardinality = _cardinality;
304 		if (_category)
305 			strncpy8 (category, _category, PClassInfo::kCategorySize);
306 		if (_name)
307 			strncpy16 (name, _name, PClassInfo::kNameSize);
308 		classFlags = static_cast<uint32> (_classFlags);
309 		if (_subCategories)
310 			strncpy8 (subCategories, _subCategories, kSubCategoriesSize);
311 		if (_vendor)
312 			strncpy16 (vendor, _vendor, kVendorSize);
313 		if (_version)
314 			strncpy16 (version, _version, kVersionSize);
315 		if (_sdkVersion)
316 			strncpy16 (sdkVersion, _sdkVersion, kVersionSize);
317 	}
318 #if SMTG_CPP11
PClassInfoWPClassInfoW319 	constexpr PClassInfoW ()
320 	: cid ()
321 	, cardinality ()
322 	, category ()
323 	, name ()
324 	, classFlags ()
325 	, subCategories ()
326 	, vendor ()
327 	, version ()
328 	, sdkVersion ()
329 	{
330 	}
331 #else
PClassInfoWPClassInfoW332 	PClassInfoW () { memset (this, 0, sizeof (PClassInfoW)); }
333 #endif
334 
fromAsciiPClassInfoW335 	void fromAscii (const PClassInfo2& ci2)
336 	{
337 		memcpy (cid, ci2.cid, sizeof (TUID));
338 		cardinality = ci2.cardinality;
339 		strncpy8 (category, ci2.category, PClassInfo::kCategorySize);
340 		str8ToStr16 (name, ci2.name, PClassInfo::kNameSize);
341 		classFlags = ci2.classFlags;
342 		strncpy8 (subCategories, ci2.subCategories, kSubCategoriesSize);
343 
344 		str8ToStr16 (vendor, ci2.vendor, kVendorSize);
345 		str8ToStr16 (version, ci2.version, kVersionSize);
346 		str8ToStr16 (sdkVersion, ci2.sdkVersion, kVersionSize);
347 	}
348 };
349 
350 
351 //------------------------------------------------------------------------
352 //  IPluginFactory3 interface declaration
353 //------------------------------------------------------------------------
354 /**	Version 3 of class factory supporting PClassInfoW.
355 \ingroup pluginBase
356 \copydoc IPluginFactory
357 */
358 //------------------------------------------------------------------------
359 class IPluginFactory3 : public IPluginFactory2
360 {
361 public:
362 //------------------------------------------------------------------------
363 	/** Returns the unicode class info for a given index. */
364 	virtual tresult PLUGIN_API getClassInfoUnicode (int32 index, PClassInfoW* info) = 0;
365 
366 	/** Receives information about host*/
367 	virtual tresult PLUGIN_API setHostContext (FUnknown* context) = 0;
368 
369 //------------------------------------------------------------------------
370 	static const FUID iid;
371 };
372 DECLARE_CLASS_IID (IPluginFactory3, 0x4555A2AB, 0xC1234E57, 0x9B122910, 0x36878931)
373 //------------------------------------------------------------------------
374 } // namespace Steinberg
375 
376 
377 //------------------------------------------------------------------------
378 #define LICENCE_UID(l1, l2, l3, l4) \
379 { \
380 	(int8)((l1 & 0xFF000000) >> 24), (int8)((l1 & 0x00FF0000) >> 16), \
381 	(int8)((l1 & 0x0000FF00) >>  8), (int8)((l1 & 0x000000FF)      ), \
382 	(int8)((l2 & 0xFF000000) >> 24), (int8)((l2 & 0x00FF0000) >> 16), \
383 	(int8)((l2 & 0x0000FF00) >>  8), (int8)((l2 & 0x000000FF)      ), \
384 	(int8)((l3 & 0xFF000000) >> 24), (int8)((l3 & 0x00FF0000) >> 16), \
385 	(int8)((l3 & 0x0000FF00) >>  8), (int8)((l3 & 0x000000FF)      ), \
386 	(int8)((l4 & 0xFF000000) >> 24), (int8)((l4 & 0x00FF0000) >> 16), \
387 	(int8)((l4 & 0x0000FF00) >>  8), (int8)((l4 & 0x000000FF)      )  \
388 }
389 
390 
391 //------------------------------------------------------------------------
392 // GetPluginFactory
393 //------------------------------------------------------------------------
394 /**  Plug-in entry point.
395 \ingroup pluginBase
396 Any Plug-in must define and export this function. \n
397 A typical implementation of GetPluginFactory looks like this
398 						\code
399 	IPluginFactory* PLUGIN_API GetPluginFactory ()
400 	{
401 		if (!gPluginFactory)
402 		{
403 			static PFactoryInfo factoryInfo =
404 			{
405 				"My Company Name",
406 				"http://www.mywebpage.com",
407 				"mailto:myemail@address.com",
408 				PFactoryInfo::kNoFlags
409 			};
410 
411 			gPluginFactory = new CPluginFactory (factoryInfo);
412 
413 			static PClassInfo componentClass =
414 			{
415 				INLINE_UID (0x00000000, 0x00000000, 0x00000000, 0x00000000), // replace by a valid uid
416 				1,
417 				"Service",    // category
418 				"Name"
419 			};
420 
421 			gPluginFactory->registerClass (&componentClass, MyComponentClass::newInstance);
422 		}
423 		else
424 			gPluginFactory->addRef ();
425 
426 		return gPluginFactory;
427 	}
428 					\endcode
429 \see \ref loadPlugin
430 */
431 //------------------------------------------------------------------------
432 extern "C"
433 {
434 	Steinberg::IPluginFactory* PLUGIN_API GetPluginFactory ();
435 	typedef Steinberg::IPluginFactory* (PLUGIN_API *GetFactoryProc) ();
436 }
437