clap-wrapper 0.2.1

An easy way to use clap-wrapper in your audio plugins!
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
//-----------------------------------------------------------------------------
// Flags       : clang-format SMTGSequencer
// Project     : SDK Core
//
// Category    : SDK Core Interfaces
// Filename    : pluginterfaces/base/funknownimpl.h
// Created by  : Steinberg, 10/2021
// Description : Steinberg Module Architecture Interface Implementation Helper
//
//-----------------------------------------------------------------------------
// 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/funknown.h"
#include <atomic>
#include <type_traits>

//------------------------------------------------------------------------
#if !(SMTG_CPP11)
#error "C++11 is required for this header"
#endif

// clang-format off
/**
This header provides classes for working with FUnknown.

An interface which shall support Steinbergs Module Architecture should inherit from U::Unknown and provide a typedef
@c IID of type U::UID.

On OS X you can generate an U::UID and copy it to the clipboard with the following shell command:
@code
uuidgen | { read id; echo -n "using IID = U::UID<0x${id:0:8}, 0x${id:9:4}${id:14:4}, 0x${id:19:4}${id:24:4}, 0x${id:28:8}>;" ; } | pbcopy
@endcode

Example:
@code{.cpp}
struct IFoo : public U::Unknown
{
    // Use a generated random uid here.
    using IID = U::UID<0x01234567, 0x89012345, 0x67890123, 0x45678901>;

    virtual void bar () = 0;
};
@endcode

A class implementing the interface @c IFoo uses the U::Implements template to specify the
interfaces it implements. All interfaces which the class should derive from need to be listed in the
U::Directly template.

Example:
@code{.cpp}
struct FooImpl : public U::Implements<U::Directly<IFoo>>
{
    void bar () override {}
};
@endcode

To check if a class can provide a specific interface use the U::cast function.

Example:
@code{.cpp}
void test (U::Unknown* obj)
{
    if (auto foo = U::cast<IFoo> (obj))
    {
        // obj provided IFoo
    }
}
@endcode

The U::Implements class supports a second template parameter U::Indirectly for specifying
a list of interfaces which should be available via @c queryInterface but not inherited from.
This is useful if an interface extends another interface.

Example:
@code{.cpp}
struct IBar : public IFoo
{
    using IID = U::UID<0x11223344, 0x55667788, 0x99001122, 0x33445566>;

    virtual void baz () = 0;
};

struct BarImpl : public U::Implements<U::Directly<IBar>, U::Indirectly<IFoo>>
{
    void bar () override {}
    void baz () override {}
};
@endcode

In some cases a class shall be extended and an additional interface implemented.
This is possible with the U::Extends template which is a generalization of the U::Implements
template and allows specifying a base class from which should be inherited.

Example:
@code{.cpp}
struct ITest : public U::Unknown
{
    using IID = U::UID<0x99887766, 0x55443322, 0x11009988, 0x77665544>;

    virtual bool equal (int a, int b) const = 0;
};

struct TestImpl : public U::Extends<FooImpl, U::Directly<ITest>>
{
    bool equal (int a, int b) const override { return a == b; }
};
@endcode

To pass arbitrary arguments to the specified base class one can use the inherited @c Base
typedef. All arguments passed to @c Base are automatically perfectly forwarded to the base class.

In the following example the value 42 is passed to the @c AlternativeFooImpl base class:
@code{.cpp}
struct AlternativeFooImpl : public U::Implements<U::Directly<IFoo>>
{
    AlternativeFooImpl (int dummy = 0) : dummy {dummy} {}
    void bar () override {}

    int dummy;
};

struct AlternativeTestImpl : public U::Extends<AlternativeFooImpl, U::Directly<ITest>>
{
    AlternativeTestImpl () : Base {42} {}

    bool equal (int a, int b) const override { return a == b; }
};
@endcode
*/
// clang-format on

//------------------------------------------------------------------------
namespace Steinberg {
namespace FUnknownImpl {

/** Typedef to keep everything in this namespace. */
using Unknown = FUnknown;

/** A base class which hides the FUnknown::iid static var */
struct HideIIDBase : FUnknown
{
	using iid = void;
};

/** Common destroyer policy for ski object instances.*/
struct Destroyer
{
	template <typename UnknownT>
	static void destroy (UnknownT* ptr)
	{
		if (!!ptr)
			ptr->release ();
	}
};

template <typename Base, typename D, typename I>
class ImplementsImpl;

/**
 *  This class provides a compile-time uid and enables  interfaces to specify a UID as a simple
 *  typedef. This way the FUID, DECLARE_CLASS_IID and DEF_CLASS_IID code can be omitted.
 */
template <uint32 t1, uint32 t2, uint32 t3, uint32 t4>
struct UID
{
	enum : int8
	{
		l1_1 = static_cast<int8> ((t1 & 0xFF000000) >> 24),
		l1_2 = static_cast<int8> ((t1 & 0x00FF0000) >> 16),
		l1_3 = static_cast<int8> ((t1 & 0x0000FF00) >> 8),
		l1_4 = static_cast<int8> ((t1 & 0x000000FF)),
		l2_1 = static_cast<int8> ((t2 & 0xFF000000) >> 24),
		l2_2 = static_cast<int8> ((t2 & 0x00FF0000) >> 16),
		l2_3 = static_cast<int8> ((t2 & 0x0000FF00) >> 8),
		l2_4 = static_cast<int8> ((t2 & 0x000000FF)),
		l3_1 = static_cast<int8> ((t3 & 0xFF000000) >> 24),
		l3_2 = static_cast<int8> ((t3 & 0x00FF0000) >> 16),
		l3_3 = static_cast<int8> ((t3 & 0x0000FF00) >> 8),
		l3_4 = static_cast<int8> ((t3 & 0x000000FF)),
		l4_1 = static_cast<int8> ((t4 & 0xFF000000) >> 24),
		l4_2 = static_cast<int8> ((t4 & 0x00FF0000) >> 16),
		l4_3 = static_cast<int8> ((t4 & 0x0000FF00) >> 8),
		l4_4 = static_cast<int8> ((t4 & 0x000000FF))
	};

	UID () = delete;

	static constexpr TUID data = {
#if COM_COMPATIBLE
	    l1_4, l1_3, l1_2, l1_1, l2_2, l2_1, l2_4, l2_3,
#else
	    l1_1, l1_2, l1_3, l1_4, l2_1, l2_2, l2_3, l2_4,
#endif
	    l3_1, l3_2, l3_3, l3_4, l4_1, l4_2, l4_3, l4_4,
	};

	static const TUID& toTUID () { return data; }
};

/** @return the TUID for an interface. */
template <typename T>
const TUID& getTUID ()
{
	return ::Steinberg::getTUID<T> ();
}

/**
 *  Checks if the given Unknown can provide the specified interface and returns it in an IPtr.
 *
 *  @return an IPtr pointing to an instance of the requested interface or nullptr in case the
 *          object does not provide the interface.
 */
template <typename I>
IPtr<I> cast (Unknown* u)
{
	I* out = nullptr;
	return u && u->queryInterface (getTUID<I> (), reinterpret_cast<void**> (&out)) == kResultOk ?
	           owned (out) :
	           nullptr;
}

/** Casts to Unknown* and then to the specified interface. */
template <typename I, typename S, typename T, typename U>
IPtr<I> cast (ImplementsImpl<S, T, U>* u)
{
	return cast<I> (u->unknownCast ());
}

/** Casts to Unknown* and then to the specified interface. */
template <typename I, typename T>
IPtr<I> cast (const IPtr<T>& u)
{
	return cast<I> (u.get ());
}

//------------------------------------------------------------------------
namespace Detail {

/**
 *  This struct implements reference counting for the @c U::Implements template.
 *  It also provides a @c queryInterface method stub to support @c queryInterface
 *  call made in the @c U::Implements template.
 */
struct RefCounted
{
//------------------------------------------------------------------------
	RefCounted () = default;
	RefCounted (const RefCounted&) {}
	RefCounted (RefCounted&& other) SMTG_NOEXCEPT : refCount {other.refCount.load ()} {}
	virtual ~RefCounted () = default;

	RefCounted& operator= (const RefCounted&) { return *this; }
	RefCounted& operator= (RefCounted&& other) SMTG_NOEXCEPT
	{
		refCount = other.refCount.load ();
		return *this;
	}

	uint32 PLUGIN_API addRef () { return ++refCount; }

	uint32 PLUGIN_API release ()
	{
		auto rc = --refCount;
		if (rc == 0)
		{
			destroyInstance ();
			refCount = -1000;
			delete this;
			return uint32 ();
		}
		return rc;
	}

//------------------------------------------------------------------------
private:
	virtual void destroyInstance () {}

	std::atomic<int32> refCount {1};
};

//------------------------------------------------------------------------
struct NonDestroyable
{
//------------------------------------------------------------------------
	NonDestroyable () = default;
	virtual ~NonDestroyable () = default;
	uint32 PLUGIN_API addRef () { return 1000; }
	uint32 PLUGIN_API release () { return 1000; }

private:
	virtual void destroyInstance () {}
};

//------------------------------------------------------------------------
template <typename T>
struct QueryInterfaceEnd : T
{
//------------------------------------------------------------------------
	tresult PLUGIN_API queryInterface (const TUID /*iid*/, void** obj)
	{
		*obj = nullptr;
		return kNoInterface;
	}
//------------------------------------------------------------------------
};

//------------------------------------------------------------------------
} // Detail

/**
 *  This struct is used to group a list of interfaces from which should be inherited and which
 *  should be available via the @c queryInterface method.
 */
template <typename... T>
struct Directly
{
};

/**
 *  This struct is used to group a list of interfaces from which should not be inherited but which
 *  should be available via the @c queryInterface method.
 */
template <typename... T>
struct Indirectly
{
};

template <typename Base, typename D, typename I>
class ImplementsImpl
{
	static_assert (sizeof (Base) == -1, "use U::Directly and U::Indirectly to specify interfaces");
};

template <typename Base, typename... DirectInterfaces, typename... IndirectInterfaces>
class ImplementsImpl<Base, Indirectly<IndirectInterfaces...>, Directly<DirectInterfaces...>>
{
	static_assert (sizeof (Base) == -1, "U::Indirectly only allowed after U::Directly");
};

/** This class implements the required virtual methods for the U::Unknown class. */
template <typename BaseClass, typename I, typename... DirectIFs, typename... IndirectIFs>
class ImplementsImpl<BaseClass, Directly<I, DirectIFs...>, Indirectly<IndirectIFs...>>
: public BaseClass, public I, public DirectIFs...
{
public:
//------------------------------------------------------------------------
	/**
	 *  This is a convenience typedef for the deriving class to pass arguments to the
	 *  constructor, which are in turn passed to the base class of this class.
	 */
	using Base = ImplementsImpl<BaseClass, Directly<I, DirectIFs...>, Indirectly<IndirectIFs...>>;

	template <typename... Args>
	ImplementsImpl (Args&&... args) : BaseClass {std::forward<Args> (args)...}
	{
	}

	tresult PLUGIN_API queryInterface (const TUID tuid, void** obj) override
	{
		if (!obj)
			return kInvalidArgument;

		if (queryInterfaceImpl<I, DirectIFs...> (tuid, *obj) ||
		    queryInterfaceImpl<IndirectIFs...> (tuid, *obj))
		{
			static_cast<Unknown*> (*obj)->addRef ();
			return kResultOk;
		}

		return BaseClass::queryInterface (tuid, obj);
	}

	uint32 PLUGIN_API addRef () override { return BaseClass::addRef (); }
	uint32 PLUGIN_API release () override { return BaseClass::release (); }

	Unknown* unknownCast () { return static_cast<Unknown*> (static_cast<I*> (this)); }

//------------------------------------------------------------------------
private:
	template <typename Interface>
	inline constexpr bool match (const TUID tuid) const noexcept
	{
		return reinterpret_cast<const uint64*> (tuid)[0] ==
		           reinterpret_cast<const uint64*> (getTUID<Interface> ())[0] &&
		       reinterpret_cast<const uint64*> (tuid)[1] ==
		           reinterpret_cast<const uint64*> (getTUID<Interface> ())[1];
	}

	template <int = 0>
	inline constexpr bool queryInterfaceImpl (const TUID, void*&) const noexcept
	{
		return false;
	}

	template <typename Interface, typename... RemainingInterfaces>
	inline bool queryInterfaceImpl (const TUID tuid, void*& obj) noexcept
	{
		if (match<Interface> (tuid) || match<Unknown> (tuid))
		{
			obj = static_cast<Interface*> (this);
			return true;
		}

		obj = getInterface<RemainingInterfaces...> (tuid);
		return obj != nullptr;
	}

	template <int = 0>
	inline constexpr void* getInterface (const TUID) const noexcept
	{
		return nullptr;
	}

	template <typename Interface, typename... RemainingInterfaces>
	inline void* getInterface (const TUID tuid) noexcept
	{
		return match<Interface> (tuid) ? static_cast<Interface*> (this) :
		                                 getInterface<RemainingInterfaces...> (tuid);
	}
};

/** This typedef enables using a custom base class with the interface implementation. */
template <typename BaseClass, typename D, typename I = Indirectly<>>
using Extends = ImplementsImpl<BaseClass, D, I>;

/** This typedef provides the interface implementation. */
template <typename D, typename I = Indirectly<>>
using Implements = ImplementsImpl<Detail::QueryInterfaceEnd<Detail::RefCounted>, D, I>;

/** This typedef provides the interface implementation for objects which should not be destroyed via
 *	FUnknown::release (like singletons). */
template <typename D, typename I = Indirectly<>>
using ImplementsNonDestroyable =
    ImplementsImpl<Detail::QueryInterfaceEnd<Detail::NonDestroyable>, D, I>;

//------------------------------------------------------------------------
} // FUnknownImpl

//------------------------------------------------------------------------
/** Shortcut namespace for implementing FUnknown based objects. */
namespace U {

using Unknown = FUnknownImpl::HideIIDBase;
using FUnknownImpl::UID;
using FUnknownImpl::Extends;
using FUnknownImpl::Implements;
using FUnknownImpl::ImplementsNonDestroyable;
using FUnknownImpl::Directly;
using FUnknownImpl::Indirectly;
using FUnknownImpl::cast;
using FUnknownImpl::getTUID;

//------------------------------------------------------------------------
} // namespace U
} // namespace Steinberg