1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-09 23:34:20 +00:00
JUCE/modules/juce_audio_plugin_client/AU/AudioUnitSDK/ComponentBase.h

162 lines
5.6 KiB
Objective-C

/*!
@file AudioUnitSDK/ComponentBase.h
@copyright © 2000-2021 Apple Inc. All rights reserved.
*/
#ifndef AudioUnitSDK_ComponentBase_h
#define AudioUnitSDK_ComponentBase_h
// module
#include <AudioUnitSDK/AUUtility.h>
// OS
#include <AudioToolbox/AudioUnit.h>
// std
#include <array>
#include <mutex>
#include <new>
namespace ausdk {
/*!
@class ComponentBase
@brief Base class for implementing an `AudioComponentInstance`.
*/
class ComponentBase {
public:
/// Construct given an AudioComponentInstance, typically from APFactory::Constuct.
explicit ComponentBase(AudioComponentInstance inInstance);
virtual ~ComponentBase() = default;
ComponentBase(const ComponentBase&) = delete;
ComponentBase(ComponentBase&&) = delete;
ComponentBase& operator=(const ComponentBase&) = delete;
ComponentBase& operator=(ComponentBase&&) = delete;
/// Called from dispatchers after constructing an instance.
void DoPostConstructor();
/// Called from dispatchers before destroying an instance.
void DoPreDestructor();
/// Obtain the wrapped `AudioComponentInstance` (underlying type of `AudioUnit`, `AudioCodec`,
/// and others).
[[nodiscard]] AudioComponentInstance GetComponentInstance() const noexcept
{
return mComponentInstance;
}
/// Return the instance's `AudioComponentDescription`.
[[nodiscard]] AudioComponentDescription GetComponentDescription() const;
/// Component dispatch method.
static OSStatus AP_Open(void* self, AudioComponentInstance compInstance);
/// Component dispatch method.
static OSStatus AP_Close(void* self);
/// A mutex which is held during `Open`, since some AU's and the Component Manager itself
/// are not thread-safe against globals.
static std::recursive_mutex& InitializationMutex();
protected:
// subclasses are free to to override these methods to add functionality
virtual void PostConstructor() {}
virtual void PreDestructor() {}
// these methods, however, are reserved for override only within this SDK
virtual void PostConstructorInternal() {}
virtual void PreDestructorInternal() {}
private:
AudioComponentInstance mComponentInstance;
};
/*!
@class AudioComponentPlugInInstance
@brief Object which implements an AudioComponentPlugInInterface for the framework, and
which holds the C++ implementation object.
*/
struct AudioComponentPlugInInstance {
// The AudioComponentPlugInInterface must remain first
AudioComponentPlugInInterface mPlugInInterface;
void* (*mConstruct)(void* memory, AudioComponentInstance ci);
void (*mDestruct)(void* memory);
std::array<void*, 2> mPad; // pad to a 16-byte boundary (in either 32 or 64 bit mode)
UInt32
mInstanceStorage; // the ACI implementation object is constructed into this memory
// this member is just a placeholder. it is aligned to a 16byte boundary
};
/*!
@class APFactory
@tparam APMethodLookup A class (e.g. AUBaseLookup) which provides a method selector lookup
function.
@tparam Implementor The class which implements the full plug-in (AudioUnit) interface.
@brief Provides an AudioComponentFactoryFunction and a convenience wrapper for
AudioComponentRegister.
*/
template <class APMethodLookup, class Implementor>
class APFactory {
public:
static void* Construct(void* memory, AudioComponentInstance compInstance)
{
return new (memory) Implementor(compInstance); // NOLINT manual memory management
}
static void Destruct(void* memory) { static_cast<Implementor*>(memory)->~Implementor(); }
// This is the AudioComponentFactoryFunction. It returns an AudioComponentPlugInInstance.
// The actual implementation object is not created until Open().
static AudioComponentPlugInInterface* Factory(const AudioComponentDescription* /* inDesc */)
{
auto* const acpi = // NOLINT owning memory
static_cast<AudioComponentPlugInInstance*>(malloc( // NOLINT manual memory management
offsetof(AudioComponentPlugInInstance, mInstanceStorage) + sizeof(Implementor)));
acpi->mPlugInInterface.Open = ComponentBase::AP_Open;
acpi->mPlugInInterface.Close = ComponentBase::AP_Close;
acpi->mPlugInInterface.Lookup = APMethodLookup::Lookup;
acpi->mPlugInInterface.reserved = nullptr;
acpi->mConstruct = Construct;
acpi->mDestruct = Destruct;
acpi->mPad[0] = nullptr;
acpi->mPad[1] = nullptr;
return &acpi->mPlugInInterface;
}
// This is for runtime registration (not for plug-ins loaded from bundles).
static AudioComponent Register(
UInt32 type, UInt32 subtype, UInt32 manuf, CFStringRef name, UInt32 vers, UInt32 flags = 0)
{
const AudioComponentDescription desc = { type, subtype, manuf, flags, 0 };
return AudioComponentRegister(&desc, name, vers, Factory);
}
};
#ifndef AUSDK_EXPORT
#if __GNUC__
#define AUSDK_EXPORT __attribute__((visibility("default"))) // NOLINT
#else
#warning export?
#endif
#endif
/// Macro to generate the factory function for the specified Audio Component. Factory is an
/// APFactory such as AUBaseFactory. Class is the name of the final ComponentBase class which
/// implements instances of the class.
#define AUSDK_COMPONENT_ENTRY(FactoryType, Class) /* NOLINT macro */ \
AUSDK_EXPORT \
extern "C" void* Class##Factory(const AudioComponentDescription* inDesc); \
extern "C" void* Class##Factory(const AudioComponentDescription* inDesc) \
{ \
return FactoryType<Class>::Factory(inDesc); /* NOLINT parens */ \
}
} // namespace ausdk
#endif // AudioUnitSDK_ComponentBase_h