diff --git a/distrho/src/DistrhoPluginAU.cpp b/distrho/src/DistrhoPluginAU.cpp index a665da79..8a6a5616 100644 --- a/distrho/src/DistrhoPluginAU.cpp +++ b/distrho/src/DistrhoPluginAU.cpp @@ -21,38 +21,134 @@ #include "DistrhoPluginInternal.hpp" #include "../DistrhoPluginUtils.hpp" -// #define CA_BASIC_AU_FEATURES 1 -#define CA_NO_AU_UI_FEATURES 1 -#define CA_USE_AUDIO_PLUGIN_ONLY 1 -#define TARGET_OS_MAC 1 - #include -#include #define TRACE d_stderr("////////--------------------------------------------------------------- %s %d", __PRETTY_FUNCTION__, __LINE__); -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunused-parameter" - -#include "au/MusicDeviceBase.h" - -#pragma clang diagnostic pop - -#ifndef TARGET_OS_MAC -#error TARGET_OS_MAC missing -#endif - START_NAMESPACE_DISTRHO // -------------------------------------------------------------------------------------------------------------------- -#if DISTRHO_PLUGIN_WANT_MIDI_INPUT || DISTRHO_PLUGIN_WANT_MIDI_OUTPUT -typedef MusicDeviceBase PluginBase; -#define PluginBaseFactory AUMIDIEffectFactory -#else -typedef AUBase PluginBase; -#define PluginBaseFactory AUBaseFactory -#endif +static const char* AudioUnitPropertyID2Str(const AudioUnitPropertyID prop) noexcept +{ + switch (prop) + { + #define PROP(s) case s: return #s; + PROP(kAudioUnitProperty_ClassInfo) + PROP(kAudioUnitProperty_MakeConnection) + PROP(kAudioUnitProperty_SampleRate) + PROP(kAudioUnitProperty_ParameterList) + PROP(kAudioUnitProperty_ParameterInfo) + PROP(kAudioUnitProperty_StreamFormat) + PROP(kAudioUnitProperty_ElementCount) + PROP(kAudioUnitProperty_Latency) + PROP(kAudioUnitProperty_SupportedNumChannels) + PROP(kAudioUnitProperty_MaximumFramesPerSlice) + PROP(kAudioUnitProperty_ParameterValueStrings) + PROP(kAudioUnitProperty_AudioChannelLayout) + PROP(kAudioUnitProperty_TailTime) + PROP(kAudioUnitProperty_BypassEffect) + PROP(kAudioUnitProperty_LastRenderError) + PROP(kAudioUnitProperty_SetRenderCallback) + PROP(kAudioUnitProperty_FactoryPresets) + PROP(kAudioUnitProperty_RenderQuality) + PROP(kAudioUnitProperty_HostCallbacks) + PROP(kAudioUnitProperty_InPlaceProcessing) + PROP(kAudioUnitProperty_ElementName) + PROP(kAudioUnitProperty_SupportedChannelLayoutTags) + PROP(kAudioUnitProperty_PresentPreset) + PROP(kAudioUnitProperty_DependentParameters) + PROP(kAudioUnitProperty_InputSamplesInOutput) + PROP(kAudioUnitProperty_ShouldAllocateBuffer) + PROP(kAudioUnitProperty_FrequencyResponse) + PROP(kAudioUnitProperty_ParameterHistoryInfo) + PROP(kAudioUnitProperty_NickName) + PROP(kAudioUnitProperty_OfflineRender) + PROP(kAudioUnitProperty_ParameterIDName) + PROP(kAudioUnitProperty_ParameterStringFromValue) + PROP(kAudioUnitProperty_ParameterClumpName) + PROP(kAudioUnitProperty_ParameterValueFromString) + PROP(kAudioUnitProperty_PresentationLatency) + PROP(kAudioUnitProperty_ClassInfoFromDocument) + PROP(kAudioUnitProperty_RequestViewController) + PROP(kAudioUnitProperty_ParametersForOverview) + PROP(kAudioUnitProperty_SupportsMPE) + PROP(kAudioUnitProperty_RenderContextObserver) + PROP(kAudioUnitProperty_LastRenderSampleTime) + PROP(kAudioUnitProperty_LoadedOutOfProcess) + #if !TARGET_OS_IPHONE + PROP(kAudioUnitProperty_FastDispatch) + PROP(kAudioUnitProperty_SetExternalBuffer) + PROP(kAudioUnitProperty_GetUIComponentList) + PROP(kAudioUnitProperty_CocoaUI) + PROP(kAudioUnitProperty_IconLocation) + PROP(kAudioUnitProperty_AUHostIdentifier) + #endif + PROP(kAudioUnitProperty_MIDIOutputCallbackInfo) + PROP(kAudioUnitProperty_MIDIOutputCallback) + PROP(kAudioUnitProperty_MIDIOutputEventListCallback) + PROP(kAudioUnitProperty_AudioUnitMIDIProtocol) + PROP(kAudioUnitProperty_HostMIDIProtocol) + PROP(kAudioUnitProperty_MIDIOutputBufferSizeHint) + #undef PROP + } + return "[unknown]"; +} + +static const char* AudioUnitScope2Str(const AudioUnitScope scope) noexcept +{ + switch (scope) + { + #define SCOPE(s) case s: return #s; + SCOPE(kAudioUnitScope_Global) + SCOPE(kAudioUnitScope_Input) + SCOPE(kAudioUnitScope_Output) + SCOPE(kAudioUnitScope_Group) + SCOPE(kAudioUnitScope_Part) + SCOPE(kAudioUnitScope_Note) + SCOPE(kAudioUnitScope_Layer) + SCOPE(kAudioUnitScope_LayerItem) + #undef SCOPE + } + return "[unknown]"; +} + +static const char* AudioUnitSelector2Str(const SInt16 selector) noexcept +{ + switch (selector) + { + #define SEL(s) case s: return #s; + SEL(kAudioUnitInitializeSelect) + SEL(kAudioUnitUninitializeSelect) + SEL(kAudioUnitGetPropertyInfoSelect) + SEL(kAudioUnitGetPropertySelect) + SEL(kAudioUnitSetPropertySelect) + SEL(kAudioUnitAddPropertyListenerSelect) + SEL(kAudioUnitRemovePropertyListenerSelect) + SEL(kAudioUnitRemovePropertyListenerWithUserDataSelect) + SEL(kAudioUnitAddRenderNotifySelect) + SEL(kAudioUnitRemoveRenderNotifySelect) + SEL(kAudioUnitGetParameterSelect) + SEL(kAudioUnitSetParameterSelect) + SEL(kAudioUnitScheduleParametersSelect) + SEL(kAudioUnitRenderSelect) + SEL(kAudioUnitResetSelect) + SEL(kAudioUnitComplexRenderSelect) + SEL(kAudioUnitProcessSelect) + SEL(kAudioUnitProcessMultipleSelect) + SEL(kMusicDeviceMIDIEventSelect) + SEL(kMusicDeviceSysExSelect) + SEL(kMusicDevicePrepareInstrumentSelect) + SEL(kMusicDeviceReleaseInstrumentSelect) + SEL(kMusicDeviceStartNoteSelect) + SEL(kMusicDeviceStopNoteSelect) + SEL(kMusicDeviceMIDIEventListSelect) + SEL(kAudioOutputUnitStartSelect) + SEL(kAudioOutputUnitStopSelect) + #undef SEL + } + return "[unknown]"; +} // -------------------------------------------------------------------------------------------------------------------- @@ -66,261 +162,17 @@ static constexpr const requestParameterValueChangeFunc requestParameterValueChan static constexpr const updateStateValueFunc updateStateValueCallback = nullptr; #endif -class PluginHolder -{ -public: - PluginExporter fPlugin; - - #if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS != 0 - struct BusInfo { - char name[32]; - uint32_t numChannels; - bool hasPair; - bool isCV; - bool isMain; - uint32_t groupId; - }; - std::vector fAudioInputBuses, fAudioOutputBuses; - bool fUsingCV; - #endif - - PluginHolder() - : fPlugin(this, writeMidiCallback, requestParameterValueChangeCallback, updateStateValueCallback) - #if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS != 0 - , fAudioInputBuses() - , fAudioOutputBuses() - , fUsingCV(false) - #endif - { - #if DISTRHO_PLUGIN_NUM_INPUTS != 0 - fillInBusInfoDetails(); - #endif - #if DISTRHO_PLUGIN_NUM_OUTPUTS != 0 - fillInBusInfoDetails(); - #endif - #if DISTRHO_PLUGIN_NUM_INPUTS != 0 && DISTRHO_PLUGIN_NUM_OUTPUTS != 0 - fillInBusInfoPairs(); - #endif - } - - // virtual ~PluginHolder() {} - -protected: - uint32_t getPluginBusCount(const bool isInput) noexcept - { - #if DISTRHO_PLUGIN_NUM_INPUTS != 0 - if (isInput) - return fAudioInputBuses.size(); - #endif - #if DISTRHO_PLUGIN_NUM_OUTPUTS != 0 - if (!isInput) - return fAudioOutputBuses.size(); - #endif - return 0; - } - -private: - #if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS != 0 - template - void fillInBusInfoDetails() - { - constexpr const uint32_t numPorts = isInput ? DISTRHO_PLUGIN_NUM_INPUTS : DISTRHO_PLUGIN_NUM_OUTPUTS; - std::vector& busInfos(isInput ? fAudioInputBuses : fAudioOutputBuses); - - enum { - kPortTypeNull, - kPortTypeAudio, - kPortTypeSidechain, - kPortTypeCV, - kPortTypeGroup - } lastSeenPortType = kPortTypeNull; - uint32_t lastSeenGroupId = kPortGroupNone; - uint32_t nonGroupAudioId = 0; - uint32_t nonGroupSidechainId = 0x20000000; - - for (uint32_t i=0; i(ptr)->writeMidi(midiEvent); - } - #endif - - #if DISTRHO_PLUGIN_WANT_PARAMETER_VALUE_CHANGE_REQUEST - bool requestParameterValueChange(uint32_t, float) - { - return true; - } - - static bool requestParameterValueChangeCallback(void* const ptr, const uint32_t index, const float value) - { - return static_cast(ptr)->requestParameterValueChange(index, value); - } - #endif - - #if DISTRHO_PLUGIN_WANT_STATE - bool updateState(const char*, const char*) - { - return true; - } - - static bool updateStateValueCallback(void* const ptr, const char* const key, const char* const value) - { - return static_cast(ptr)->updateState(key, value); - } - #endif -}; - -class PluginAU : public PluginHolder, - public PluginBase +class PluginAU { public: PluginAU(const AudioUnit component) - : PluginHolder(), - PluginBase(component, getPluginBusCount(true), getPluginBusCount(false)), + : fPlugin(this, writeMidiCallback, requestParameterValueChangeCallback, updateStateValueCallback), fParameterCount(fPlugin.getParameterCount()), fCachedParameterValues(nullptr) { TRACE +#if 0 if (fParameterCount != 0) { CreateElements(); @@ -342,115 +194,147 @@ class PluginAU : public PluginHolder, // static SupportedNumChannels(nullptr); + #endif } - ~PluginAU() override + ~PluginAU() { TRACE delete[] fCachedParameterValues; } -protected: - // ---------------------------------------------------------------------------------------------------------------- - // ComponentBase AU dispatch - - OSStatus Initialize() override + OSStatus auInitialize() { - TRACE - ComponentResult res; - - res = PluginBase::Initialize(); - DISTRHO_SAFE_ASSERT_INT_RETURN(res == noErr, res, res); - - setBufferSizeAndSampleRate(); - fPlugin.activate(); - return noErr; } - void Cleanup() override + OSStatus auUninitialize() { - TRACE - fPlugin.deactivate(); - PluginBase::Cleanup(); + return noErr; } - OSStatus Reset(AudioUnitScope inScope, AudioUnitElement inElement) override + OSStatus auGetPropertyInfo(const AudioUnitPropertyID inID, + const AudioUnitScope inScope, + const AudioUnitElement inElement, + UInt32& outDataSize, + Boolean& outWritable) { - TRACE - fPlugin.deactivateIfNeeded(); - - const OSStatus res = PluginBase::Reset(inScope, inElement); - - if (res == noErr) + switch (inID) { - setBufferSizeAndSampleRate(); - fPlugin.activate(); + case kAudioUnitProperty_ClassInfo: + DISTRHO_SAFE_ASSERT_UINT_RETURN(inScope == kAudioUnitScope_Global, inScope, kAudioUnitErr_InvalidScope); + /* TODO used for storing plugin state + outDataSize = sizeof(CFPropertyListRef); + outWritable = true; + */ + break; + case kAudioUnitProperty_ElementCount: + outDataSize = sizeof(UInt32); + outWritable = false; + return noErr; + #if DISTRHO_PLUGIN_WANT_LATENCY + case kAudioUnitProperty_Latency: + DISTRHO_SAFE_ASSERT_UINT_RETURN(inScope == kAudioUnitScope_Global, inScope, kAudioUnitErr_InvalidScope); + outDataSize = sizeof(Float64); + outWritable = false; + return noErr; + #endif + case kAudioUnitProperty_SupportedNumChannels: + DISTRHO_SAFE_ASSERT_UINT_RETURN(inScope == kAudioUnitScope_Global, inScope, kAudioUnitErr_InvalidScope); + outDataSize = sizeof(AUChannelInfo); + outWritable = false; + return noErr; + case kAudioUnitProperty_MaximumFramesPerSlice: + DISTRHO_SAFE_ASSERT_UINT_RETURN(inScope == kAudioUnitScope_Global, inScope, kAudioUnitErr_InvalidScope); + outDataSize = sizeof(UInt32); + outWritable = true; + return noErr; + #if DISTRHO_PLUGIN_HAS_UI + case kAudioUnitProperty_CocoaUI: + outDataSize = sizeof(AudioUnitCocoaViewInfo); + outWritable = false; + return noErr; + #endif } - return res; + return kAudioUnitErr_InvalidProperty; } - OSStatus GetPropertyInfo(const AudioUnitPropertyID inID, - const AudioUnitScope inScope, - const AudioUnitElement inElement, - UInt32& outDataSize, - Boolean& outWritable) override + OSStatus auGetProperty(const AudioUnitPropertyID inID, + const AudioUnitScope inScope, + const AudioUnitElement inElement, + void* const outData) { - TRACE - if (inScope == kAudioUnitScope_Global) + switch (inID) { - switch (inID) + case kAudioUnitProperty_ClassInfo: + /* TODO used for storing plugin state + *static_cast(outData) = nullptr; + */ + break; + #if DISTRHO_PLUGIN_WANT_LATENCY + case kAudioUnitProperty_Latency: + *static_cast(outData) = static_cast(fPlugin.getLatency()) / fPlugin.getSampleRate(); + return noErr; + #endif + case kAudioUnitProperty_SupportedNumChannels: + *static_cast(outData) = { DISTRHO_PLUGIN_NUM_INPUTS, DISTRHO_PLUGIN_NUM_OUTPUTS }; + return noErr; + case kAudioUnitProperty_MaximumFramesPerSlice: + *static_cast(outData) = fPlugin.getBufferSize(); + return noErr; + #if DISTRHO_PLUGIN_HAS_UI + case kAudioUnitProperty_CocoaUI: { - #if DISTRHO_PLUGIN_HAS_UI - case kAudioUnitProperty_CocoaUI: - outDataSize = sizeof(AudioUnitCocoaViewInfo); - outWritable = true; - return noErr; - #endif - default: - break; + AudioUnitCocoaViewInfo* const info = static_cast(outData); + + NSString* const bundlePathString = [[NSString alloc] + initWithBytes:d_nextBundlePath + length:strlen(d_nextBundlePath) + encoding:NSUTF8StringEncoding]; + + info->mCocoaAUViewBundleLocation = static_cast([[NSURL fileURLWithPath: bundlePathString] retain]); + info->mCocoaAUViewClass[0] = CFSTR("DPF_UI_ViewFactory"); + + [bundlePathString release]; } + return noErr; + #endif } - return PluginBase::GetPropertyInfo(inID, inScope, inElement, outDataSize, outWritable); + return kAudioUnitErr_InvalidProperty; } - OSStatus GetProperty(const AudioUnitPropertyID inID, - const AudioUnitScope inScope, - const AudioUnitElement inElement, - void* const outData) override + OSStatus auSetProperty(const AudioUnitPropertyID inID, + const AudioUnitScope inScope, + const AudioUnitElement inElement, + const void* const inData, + const UInt32 inDataSize) { - TRACE - if (inScope == kAudioUnitScope_Global) + switch (inID) { - switch (inID) - { - #if DISTRHO_PLUGIN_HAS_UI - case kAudioUnitProperty_CocoaUI: - if (AudioUnitCocoaViewInfo* const info = static_cast(outData)) - { - NSString* const bundlePathString = [[NSString alloc] - initWithBytes:d_nextBundlePath - length:strlen(d_nextBundlePath) - encoding:NSUTF8StringEncoding]; - - info->mCocoaAUViewBundleLocation = static_cast([[NSURL fileURLWithPath: bundlePathString] retain]); - info->mCocoaAUViewClass[0] = CFSTR("DPF_UI_ViewFactory"); - - [bundlePathString release]; - } - return noErr; - #endif - default: - break; - } + case kAudioUnitProperty_ClassInfo: + DISTRHO_SAFE_ASSERT_UINT_RETURN(inScope == kAudioUnitScope_Global, inScope, kAudioUnitErr_InvalidScope); + DISTRHO_SAFE_ASSERT_UINT_RETURN(inDataSize == sizeof(CFPropertyListRef*), inDataSize, kAudioUnitErr_InvalidPropertyValue); + /* TODO used for restoring plugin state + *static_cast(inData); + */ + break; + case kAudioUnitProperty_MaximumFramesPerSlice: + DISTRHO_SAFE_ASSERT_UINT_RETURN(inScope == kAudioUnitScope_Global, inScope, kAudioUnitErr_InvalidScope); + DISTRHO_SAFE_ASSERT_UINT_RETURN(inDataSize == sizeof(UInt32), inDataSize, kAudioUnitErr_InvalidPropertyValue); + fPlugin.setBufferSize(*static_cast(inData)); + return noErr; } - return PluginBase::GetProperty(inID, inScope, inElement, outData); + return kAudioUnitErr_InvalidProperty; } #if 0 +protected: + // ---------------------------------------------------------------------------------------------------------------- + // ComponentBase AU dispatch + OSStatus GetParameter(const AudioUnitParameterID inParameterID, const AudioUnitScope inScope, const AudioUnitElement inElement, @@ -461,7 +345,6 @@ class PluginAU : public PluginHolder, return fPlugin.getParameterValue(inParameterID); } -#endif OSStatus SetParameter(AudioUnitParameterID inParameterID, const AudioUnitScope inScope, @@ -477,12 +360,6 @@ class PluginAU : public PluginHolder, return noErr; } - bool CanScheduleParameters() const override - { - TRACE - return false; - } - OSStatus Render(AudioUnitRenderActionFlags& ioActionFlags, const AudioTimeStamp& inTimeStamp, const UInt32 nFrames) override @@ -572,194 +449,293 @@ class PluginAU : public PluginHolder, return noErr; } - #if DISTRHO_PLUGIN_WANT_LATENCY - Float64 GetLatency() override +private: + double getSampleRate() { - TRACE - return static_cast(fPlugin.getLatency()) / fPlugin.getSampleRate(); + #if DISTRHO_PLUGIN_NUM_OUTPUTS != 0 && 0 + if (AUOutputElement* const output = GetOutput(0)) + { + const double sampleRate = d_nextSampleRate = output->GetStreamFormat().mSampleRate; + return sampleRate; + } + #endif + + #if DISTRHO_PLUGIN_NUM_INPUTS != 0 && 0 + if (AUInputElement* const input = GetInput(0)) + { + const double sampleRate = d_nextSampleRate = input->GetStreamFormat().mSampleRate; + return sampleRate; + } + #endif + + return d_nextSampleRate; } - #endif - bool StreamFormatWritable(AudioUnitScope, AudioUnitElement) override + void setBufferSizeAndSampleRate() { - TRACE - return false; + fPlugin.setSampleRate(getSampleRate(), true); + fPlugin.setBufferSize(GetMaxFramesPerSlice(), true); } +#endif - UInt32 SupportedNumChannels(const AUChannelInfo** const outInfo) override - { - TRACE - static const AUChannelInfo sChannels[1] = {{ DISTRHO_PLUGIN_NUM_INPUTS, DISTRHO_PLUGIN_NUM_OUTPUTS }}; +private: + PluginExporter fPlugin; - if (outInfo != nullptr) - *outInfo = sChannels; + const uint32_t fParameterCount; + float* fCachedParameterValues; - return 1; + // ---------------------------------------------------------------------------------------------------------------- + // DPF callbacks + + #if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT + bool writeMidi(const MidiEvent&) + { + return true; } -#if 0 - bool ValidFormat(AudioUnitScope scope, AudioUnitElement element, const CAStreamBasicDescription& format) override + static bool writeMidiCallback(void* const ptr, const MidiEvent& midiEvent) { - TRACE - return false; + return static_cast(ptr)->writeMidi(midiEvent); } + #endif - OSStatus ChangeStreamFormat(AudioUnitScope scope, AudioUnitElement element, const CAStreamBasicDescription& old, const CAStreamBasicDescription& format) override + #if DISTRHO_PLUGIN_WANT_PARAMETER_VALUE_CHANGE_REQUEST + bool requestParameterValueChange(uint32_t, float) { - TRACE - return noErr; + return true; } - OSStatus StartNote(MusicDeviceInstrumentID, MusicDeviceGroupID, NoteInstanceID*, UInt32, const MusicDeviceNoteParams&) override + static bool requestParameterValueChangeCallback(void* const ptr, const uint32_t index, const float value) { - TRACE - return noErr; + return static_cast(ptr)->requestParameterValueChange(index, value); } + #endif - OSStatus StopNote(MusicDeviceGroupID, NoteInstanceID, UInt32) override + #if DISTRHO_PLUGIN_WANT_STATE + bool updateState(const char*, const char*) { - TRACE - return noErr; + return true; } -#endif - void SetMaxFramesPerSlice(const UInt32 nFrames) override + static bool updateStateValueCallback(void* const ptr, const char* const key, const char* const value) { - PluginBase::SetMaxFramesPerSlice(nFrames); + return static_cast(ptr)->updateState(key, value); + } + #endif + + DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PluginAU) +}; + +// -------------------------------------------------------------------------------------------------------------------- - DISTRHO_SAFE_ASSERT_RETURN(!fPlugin.isActive(),); - fPlugin.setBufferSize(nFrames, true); +struct AudioComponentPlugInInstance { + AudioComponentPlugInInterface acpi; + PluginAU* plugin; + + AudioComponentPlugInInstance() noexcept + : acpi(), + plugin(nullptr) + { + std::memset(&acpi, 0, sizeof(acpi)); + acpi.Open = Open; + acpi.Close = Close; + acpi.Lookup = Lookup; + acpi.reserved = NULL; } -#if 0 - UInt32 GetChannelLayoutTags(const AudioUnitScope scope, - const AudioUnitElement element, - AudioChannelLayoutTag* const outLayoutTags) override + ~AudioComponentPlugInInstance() { - TRACE - return 0; + delete plugin; } - UInt32 GetAudioChannelLayout(AudioUnitScope scope, AudioUnitElement element, - AudioChannelLayout* outLayoutPtr, Boolean& outWritable) override + static OSStatus Open(void* const self, const AudioUnit component) { - TRACE - return 0; + static_cast(self)->plugin = new PluginAU(component); + return noErr; } - OSStatus SetAudioChannelLayout(AudioUnitScope scope, AudioUnitElement element, const AudioChannelLayout* inLayout) override + static OSStatus Close(void* const self) { - TRACE + delete static_cast(self); return noErr; } -#endif -private: - double getSampleRate() + static AudioComponentMethod Lookup(const SInt16 selector) { - #if DISTRHO_PLUGIN_NUM_OUTPUTS != 0 && 0 - if (AUOutputElement* const output = GetOutput(0)) - { - const double sampleRate = d_nextSampleRate = output->GetStreamFormat().mSampleRate; - return sampleRate; - } - #endif + d_stdout("AudioComponentPlugInInstance::Lookup(%3d:%s)", selector, AudioUnitSelector2Str(selector)); - #if DISTRHO_PLUGIN_NUM_INPUTS != 0 && 0 - if (AUInputElement* const input = GetInput(0)) + switch (selector) { - const double sampleRate = d_nextSampleRate = input->GetStreamFormat().mSampleRate; - return sampleRate; + case kAudioUnitInitializeSelect: + return reinterpret_cast(Initialize); + case kAudioUnitUninitializeSelect: + return reinterpret_cast(Uninitialize); + case kAudioUnitGetPropertyInfoSelect: + return reinterpret_cast(GetPropertyInfo); + case kAudioUnitGetPropertySelect: + return reinterpret_cast(GetProperty); + case kAudioUnitSetPropertySelect: + return reinterpret_cast(SetProperty); + #if 0 + case kAudioUnitAddPropertyListenerSelect: + return reinterpret_cast(Uninitialize); + case kAudioUnitRemovePropertyListenerSelect: + return reinterpret_cast(Uninitialize); + case kAudioUnitRemovePropertyListenerWithUserDataSelect: + return reinterpret_cast(Uninitialize); + case kAudioUnitAddRenderNotifySelect: + return reinterpret_cast(Uninitialize); + case kAudioUnitRemoveRenderNotifySelect: + return reinterpret_cast(Uninitialize); + case kAudioUnitGetParameterSelect: + return reinterpret_cast(Uninitialize); + case kAudioUnitSetParameterSelect: + return reinterpret_cast(Uninitialize); + case kAudioUnitScheduleParametersSelect: + return reinterpret_cast(Uninitialize); + case kAudioUnitRenderSelect: + return reinterpret_cast(Uninitialize); + case kAudioUnitResetSelect: + return reinterpret_cast(Uninitialize); + case kAudioUnitComplexRenderSelect: + return reinterpret_cast(Uninitialize); + case kAudioUnitProcessSelect: + return reinterpret_cast(Uninitialize); + case kAudioUnitProcessMultipleSelect: + return reinterpret_cast(Uninitialize); + #endif } - #endif - return d_nextSampleRate; + return nullptr; } - void setBufferSizeAndSampleRate() + static OSStatus Initialize(AudioComponentPlugInInstance* const self) { - fPlugin.setSampleRate(getSampleRate(), true); - fPlugin.setBufferSize(GetMaxFramesPerSlice(), true); + d_stdout("AudioComponentPlugInInstance::Initialize(%p)", self); + return self->plugin->auInitialize(); } -private: - const uint32_t fParameterCount; - float* fCachedParameterValues; + static OSStatus Uninitialize(AudioComponentPlugInInstance* const self) + { + d_stdout("AudioComponentPlugInInstance::Uninitialize(%p)", self); + return self->plugin->auUninitialize(); + } - DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PluginAU) -}; + static OSStatus GetPropertyInfo(AudioComponentPlugInInstance* const self, + const AudioUnitPropertyID inID, + const AudioUnitScope inScope, + const AudioUnitElement inElement, + UInt32* const outDataSize, + Boolean* const outWritable) + { + d_stdout("AudioComponentPlugInInstance::GetPropertyInfo(%p, %2d:%s, %d:%s, %d, %p, ...)", + self, inID, AudioUnitPropertyID2Str(inID), inScope, AudioUnitScope2Str(inScope), inElement); -END_NAMESPACE_DISTRHO + UInt32 dataSize = 0; + Boolean writable = false; + const OSStatus res = self->plugin->auGetPropertyInfo(inID, inScope, inElement, dataSize, writable); -// -------------------------------------------------------------------------------------------------------------------- + if (outDataSize != nullptr) + *outDataSize = dataSize; -#ifndef verify -# define verify(assertion) __Verify(assertion) -#endif -#ifndef verify_noerr -# define verify_noerr(errorCode) __Verify_noErr(errorCode) -#endif + if (outWritable != nullptr) + *outWritable = writable; -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunused-parameter" -#pragma clang diagnostic ignored "-Wunused-private-field" + return res; + } -#include "au/AUBase.cpp" -#include "au/AUBuffer.cpp" -#if !CA_USE_AUDIO_PLUGIN_ONLY -#include "au/AUDispatch.cpp" -#endif -#include "au/AUInputElement.cpp" -#include "au/AUMIDIBase.cpp" -#include "au/AUOutputBase.cpp" -#include "au/AUOutputElement.cpp" -#include "au/AUPlugInDispatch.cpp" -#include "au/AUScopeElement.cpp" -#include "au/CAAUParameter.cpp" -#include "au/CAAudioChannelLayout.cpp" -#include "au/CAMutex.cpp" -#include "au/CAStreamBasicDescription.cpp" -#include "au/CAVectorUnit.cpp" -#include "au/ComponentBase.cpp" -#include "au/MusicDeviceBase.cpp" - -#pragma clang diagnostic pop - -#undef verify -#undef verify_noerr + static OSStatus GetProperty(AudioComponentPlugInInstance* const self, + const AudioUnitPropertyID inID, + const AudioUnitScope inScope, + const AudioUnitElement inElement, + void* const outData, + UInt32* const ioDataSize) + { + d_stdout("AudioComponentPlugInInstance::GetProperty (%p, %2d:%s, %d:%s, %d, %p, ...)", + self, inID, AudioUnitPropertyID2Str(inID), inScope, AudioUnitScope2Str(inScope), inElement); + DISTRHO_SAFE_ASSERT_RETURN(ioDataSize != nullptr, kAudio_ParamError); -// -------------------------------------------------------------------------------------------------------------------- + Boolean writable; + UInt32 outDataSize = 0; + OSStatus res; -/* -DISTRHO_PLUGIN_EXPORT -OSStatus PluginAUEntry(ComponentParameters*, PluginAU*); + if (outData == nullptr) + { + res = self->plugin->auGetPropertyInfo(inID, inScope, inElement, outDataSize, writable); + *ioDataSize = outDataSize; + return res; + } -DISTRHO_PLUGIN_EXPORT -void* PluginAUFactory(const AudioComponentDescription*); + const UInt32 inDataSize = *ioDataSize; + DISTRHO_SAFE_ASSERT_RETURN(inDataSize != 0, kAudio_ParamError); -#if DISTRHO_PLUGIN_WANT_MIDI_INPUT || DISTRHO_PLUGIN_WANT_MIDI_OUTPUT -AUDIOCOMPONENT_ENTRY(AUMIDIEffectFactory, PluginAU) -#else -AUDIOCOMPONENT_ENTRY(AUBaseFactory, PluginAU) -#endif + res = self->plugin->auGetPropertyInfo(inID, inScope, inElement, outDataSize, writable); -DISTRHO_PLUGIN_EXPORT -OSStatus PluginAUEntry(ComponentParameters* const params, PluginAU* const obj) -{ - TRACE - return ComponentEntryPoint::Dispatch(params, obj); -} -*/ + if (res != noErr) + return res; + + void* outBuffer; + uint8_t* tmpBuffer; + if (inDataSize < outDataSize) + { + tmpBuffer = new uint8_t[outDataSize]; + outBuffer = tmpBuffer; + } + else + { + tmpBuffer = nullptr; + outBuffer = outData; + } + + res = self->plugin->auGetProperty(inID, inScope, inElement, outBuffer); + + if (res != noErr) + { + *ioDataSize = 0; + return res; + } + + if (tmpBuffer != nullptr) + { + memcpy(outData, tmpBuffer, inDataSize); + delete[] tmpBuffer; + } + else + { + *ioDataSize = outDataSize; + } + + return noErr; + } + + static OSStatus SetProperty(AudioComponentPlugInInstance* const self, + const AudioUnitPropertyID inID, + const AudioUnitScope inScope, + const AudioUnitElement inElement, + const void* const inData, + const UInt32 inDataSize) + { + d_stdout("AudioComponentPlugInInstance::SetProperty(%p, %d:%s, %d:%s, %d, %d, %p, %u)", + self, inID, AudioUnitPropertyID2Str(inID), inScope, AudioUnitScope2Str(inScope), inElement, inData, inDataSize); + return self->plugin->auSetProperty(inID, inScope, inElement, inData, inDataSize); + } +}; + +// -------------------------------------------------------------------------------------------------------------------- + +END_NAMESPACE_DISTRHO DISTRHO_PLUGIN_EXPORT -void* PluginAUFactory(const AudioComponentDescription* const inDesc) +void* PluginAUFactory(const AudioComponentDescription*) { + USE_NAMESPACE_DISTRHO TRACE + if (d_nextBufferSize == 0) - d_nextBufferSize = kAUDefaultMaxFramesPerSlice; + d_nextBufferSize = 1156; if (d_isZero(d_nextSampleRate)) - d_nextSampleRate = kAUDefaultSampleRate; + d_nextSampleRate = 48000.0; if (d_nextBundlePath == nullptr) { @@ -782,9 +758,9 @@ void* PluginAUFactory(const AudioComponentDescription* const inDesc) d_nextBundlePath = bundlePath.buffer(); } - // d_nextCanRequestParameterValueChanges = true; + d_nextCanRequestParameterValueChanges = true; - return PluginBaseFactory::Factory(inDesc); + return new AudioComponentPlugInInstance(); } // --------------------------------------------------------------------------------------------------------------------