/*! @file AudioUnitSDK/ComponentBase.h @copyright © 2000-2021 Apple Inc. All rights reserved. */ #ifndef AudioUnitSDK_ComponentBase_h #define AudioUnitSDK_ComponentBase_h // module #include // OS #include // std #include #include #include 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 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 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(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(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::Factory(inDesc); /* NOLINT parens */ \ } } // namespace ausdk #endif // AudioUnitSDK_ComponentBase_h