The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

163 lines
5.6KB

  1. /*!
  2. @file AudioUnitSDK/ComponentBase.h
  3. @copyright © 2000-2021 Apple Inc. All rights reserved.
  4. */
  5. #ifndef AudioUnitSDK_ComponentBase_h
  6. #define AudioUnitSDK_ComponentBase_h
  7. // module
  8. #include <AudioUnitSDK/AUUtility.h>
  9. // OS
  10. #include <AudioToolbox/AudioUnit.h>
  11. // std
  12. #include <array>
  13. #include <mutex>
  14. #include <new>
  15. namespace ausdk {
  16. /*!
  17. @class ComponentBase
  18. @brief Base class for implementing an `AudioComponentInstance`.
  19. */
  20. class ComponentBase {
  21. public:
  22. /// Construct given an AudioComponentInstance, typically from APFactory::Constuct.
  23. explicit ComponentBase(AudioComponentInstance inInstance);
  24. virtual ~ComponentBase() = default;
  25. ComponentBase(const ComponentBase&) = delete;
  26. ComponentBase(ComponentBase&&) = delete;
  27. ComponentBase& operator=(const ComponentBase&) = delete;
  28. ComponentBase& operator=(ComponentBase&&) = delete;
  29. /// Called from dispatchers after constructing an instance.
  30. void DoPostConstructor();
  31. /// Called from dispatchers before destroying an instance.
  32. void DoPreDestructor();
  33. /// Obtain the wrapped `AudioComponentInstance` (underlying type of `AudioUnit`, `AudioCodec`,
  34. /// and others).
  35. [[nodiscard]] AudioComponentInstance GetComponentInstance() const noexcept
  36. {
  37. return mComponentInstance;
  38. }
  39. /// Return the instance's `AudioComponentDescription`.
  40. [[nodiscard]] AudioComponentDescription GetComponentDescription() const;
  41. /// Component dispatch method.
  42. static OSStatus AP_Open(void* self, AudioComponentInstance compInstance);
  43. /// Component dispatch method.
  44. static OSStatus AP_Close(void* self);
  45. /// A mutex which is held during `Open`, since some AU's and the Component Manager itself
  46. /// are not thread-safe against globals.
  47. static std::recursive_mutex& InitializationMutex();
  48. protected:
  49. // subclasses are free to to override these methods to add functionality
  50. virtual void PostConstructor() {}
  51. virtual void PreDestructor() {}
  52. // these methods, however, are reserved for override only within this SDK
  53. virtual void PostConstructorInternal() {}
  54. virtual void PreDestructorInternal() {}
  55. private:
  56. AudioComponentInstance mComponentInstance;
  57. };
  58. /*!
  59. @class AudioComponentPlugInInstance
  60. @brief Object which implements an AudioComponentPlugInInterface for the framework, and
  61. which holds the C++ implementation object.
  62. */
  63. struct AudioComponentPlugInInstance {
  64. // The AudioComponentPlugInInterface must remain first
  65. AudioComponentPlugInInterface mPlugInInterface;
  66. void* (*mConstruct)(void* memory, AudioComponentInstance ci);
  67. void (*mDestruct)(void* memory);
  68. std::array<void*, 2> mPad; // pad to a 16-byte boundary (in either 32 or 64 bit mode)
  69. UInt32
  70. mInstanceStorage; // the ACI implementation object is constructed into this memory
  71. // this member is just a placeholder. it is aligned to a 16byte boundary
  72. };
  73. /*!
  74. @class APFactory
  75. @tparam APMethodLookup A class (e.g. AUBaseLookup) which provides a method selector lookup
  76. function.
  77. @tparam Implementor The class which implements the full plug-in (AudioUnit) interface.
  78. @brief Provides an AudioComponentFactoryFunction and a convenience wrapper for
  79. AudioComponentRegister.
  80. */
  81. template <class APMethodLookup, class Implementor>
  82. class APFactory {
  83. public:
  84. static void* Construct(void* memory, AudioComponentInstance compInstance)
  85. {
  86. return new (memory) Implementor(compInstance); // NOLINT manual memory management
  87. }
  88. static void Destruct(void* memory) { static_cast<Implementor*>(memory)->~Implementor(); }
  89. // This is the AudioComponentFactoryFunction. It returns an AudioComponentPlugInInstance.
  90. // The actual implementation object is not created until Open().
  91. static AudioComponentPlugInInterface* Factory(const AudioComponentDescription* /* inDesc */)
  92. {
  93. auto* const acpi = // NOLINT owning memory
  94. static_cast<AudioComponentPlugInInstance*>(malloc( // NOLINT manual memory management
  95. offsetof(AudioComponentPlugInInstance, mInstanceStorage) + sizeof(Implementor)));
  96. acpi->mPlugInInterface.Open = ComponentBase::AP_Open;
  97. acpi->mPlugInInterface.Close = ComponentBase::AP_Close;
  98. acpi->mPlugInInterface.Lookup = APMethodLookup::Lookup;
  99. acpi->mPlugInInterface.reserved = nullptr;
  100. acpi->mConstruct = Construct;
  101. acpi->mDestruct = Destruct;
  102. acpi->mPad[0] = nullptr;
  103. acpi->mPad[1] = nullptr;
  104. return &acpi->mPlugInInterface;
  105. }
  106. // This is for runtime registration (not for plug-ins loaded from bundles).
  107. static AudioComponent Register(
  108. UInt32 type, UInt32 subtype, UInt32 manuf, CFStringRef name, UInt32 vers, UInt32 flags = 0)
  109. {
  110. const AudioComponentDescription desc = { type, subtype, manuf, flags, 0 };
  111. return AudioComponentRegister(&desc, name, vers, Factory);
  112. }
  113. };
  114. #ifndef AUSDK_EXPORT
  115. #if __GNUC__
  116. #define AUSDK_EXPORT __attribute__((visibility("default"))) // NOLINT
  117. #else
  118. #warning export?
  119. #endif
  120. #endif
  121. /// Macro to generate the factory function for the specified Audio Component. Factory is an
  122. /// APFactory such as AUBaseFactory. Class is the name of the final ComponentBase class which
  123. /// implements instances of the class.
  124. #define AUSDK_COMPONENT_ENTRY(FactoryType, Class) /* NOLINT macro */ \
  125. AUSDK_EXPORT \
  126. extern "C" void* Class##Factory(const AudioComponentDescription* inDesc); \
  127. extern "C" void* Class##Factory(const AudioComponentDescription* inDesc) \
  128. { \
  129. return FactoryType<Class>::Factory(inDesc); /* NOLINT parens */ \
  130. }
  131. } // namespace ausdk
  132. #endif // AudioUnitSDK_ComponentBase_h