From a1e8aa4278470c7a66950bc0d29723cb52320be0 Mon Sep 17 00:00:00 2001 From: reuk Date: Wed, 20 Jul 2022 13:12:59 +0100 Subject: [PATCH] AUv3 Client: Remove unnecessary base class --- .../AU/juce_AUv3_Wrapper.mm | 580 ++++++++---------- 1 file changed, 240 insertions(+), 340 deletions(-) diff --git a/modules/juce_audio_plugin_client/AU/juce_AUv3_Wrapper.mm b/modules/juce_audio_plugin_client/AU/juce_AUv3_Wrapper.mm index 6506ec2131..aaa1a16800 100644 --- a/modules/juce_audio_plugin_client/AU/juce_AUv3_Wrapper.mm +++ b/modules/juce_audio_plugin_client/AU/juce_AUv3_Wrapper.mm @@ -103,260 +103,10 @@ private: AudioProcessorHolder& operator= (AudioProcessorHolder&) = delete; }; -//============================================================================== -class JuceAudioUnitv3Base -{ -public: - JuceAudioUnitv3Base (const AudioComponentDescription& descr, - AudioComponentInstantiationOptions options, - NSError** error) - JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wobjc-method-access") - : au ([getClass().createInstance() initWithComponentDescription: descr - options: options - error: error - juceClass: this]) - JUCE_END_IGNORE_WARNINGS_GCC_LIKE - {} - - JuceAudioUnitv3Base (AUAudioUnit* audioUnit) : au (audioUnit) - { - jassert (MessageManager::getInstance()->isThisTheMessageThread()); - initialiseJuce_GUI(); - } - - virtual ~JuceAudioUnitv3Base() = default; - - //============================================================================== - AUAudioUnit* getAudioUnit() noexcept { return au; } - - //============================================================================== - virtual void reset() = 0; - - //============================================================================== - virtual AUAudioUnitPreset* getCurrentPreset() = 0; - virtual void setCurrentPreset (AUAudioUnitPreset*) = 0; - virtual NSArray* getFactoryPresets() = 0; - - virtual NSDictionary* getFullState() - { - return ObjCMsgSendSuper*> (getAudioUnit(), @selector (fullState)); - } - - virtual void setFullState (NSDictionary* state) - { - ObjCMsgSendSuper (getAudioUnit(), @selector (setFullState:), state); - } - - virtual AUParameterTree* getParameterTree() = 0; - virtual NSArray* parametersForOverviewWithCount (int) = 0; - - //============================================================================== - virtual NSTimeInterval getLatency() = 0; - virtual NSTimeInterval getTailTime() = 0; - - //============================================================================== - virtual AUAudioUnitBusArray* getInputBusses() = 0; - virtual AUAudioUnitBusArray* getOutputBusses() = 0; - virtual NSArray* getChannelCapabilities() = 0; - virtual bool shouldChangeToFormat (AVAudioFormat*, AUAudioUnitBus*) = 0; - - //============================================================================== - virtual int getVirtualMIDICableCount() = 0; - virtual bool getSupportsMPE() = 0; - virtual NSArray* getMIDIOutputNames() = 0; - - //============================================================================== - virtual AUInternalRenderBlock getInternalRenderBlock() = 0; - virtual bool getCanProcessInPlace() { return false; } - virtual bool getRenderingOffline() = 0; - virtual void setRenderingOffline (bool offline) = 0; - - virtual bool getShouldBypassEffect() - { - return (ObjCMsgSendSuper (getAudioUnit(), @selector (shouldBypassEffect)) == YES); - } - - virtual void setShouldBypassEffect (bool shouldBypass) - { - ObjCMsgSendSuper (getAudioUnit(), @selector (setShouldBypassEffect:), shouldBypass ? YES : NO); - } - - //============================================================================== - virtual NSString* getContextName() const = 0; - virtual void setContextName (NSString*) = 0; - - virtual bool allocateRenderResourcesAndReturnError (NSError **outError) - { - return (ObjCMsgSendSuper (getAudioUnit(), @selector (allocateRenderResourcesAndReturnError:), outError) == YES); - } - - virtual void deallocateRenderResources() - { - ObjCMsgSendSuper (getAudioUnit(), @selector (deallocateRenderResources)); - } - - //============================================================================== - API_AVAILABLE (macos (10.13), ios (11.0)) - virtual NSIndexSet* getSupportedViewConfigurations (NSArray*) = 0; - - API_AVAILABLE (macos (10.13), ios (11.0)) - virtual void selectViewConfiguration (AUAudioUnitViewConfiguration*) = 0; - -private: - struct Class : public ObjCClass - { - Class() : ObjCClass ("AUAudioUnit_") - { - addIvar ("cppObject"); - - JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wundeclared-selector") - addMethod (@selector (initWithComponentDescription:options:error:juceClass:), [] (id _self, - SEL, - AudioComponentDescription descr, - AudioComponentInstantiationOptions options, - NSError** error, - JuceAudioUnitv3Base* juceAU) - { - AUAudioUnit* self = _self; - - self = ObjCMsgSendSuper (self, @selector(initWithComponentDescription:options:error:), descr, options, error); - - - setThis (self, juceAU); - return self; - }); - - JUCE_END_IGNORE_WARNINGS_GCC_LIKE - - addMethod (@selector (initWithComponentDescription:options:error:), [] (id _self, - SEL, - AudioComponentDescription descr, - AudioComponentInstantiationOptions options, - NSError** error) - { - AUAudioUnit* self = _self; - - self = ObjCMsgSendSuper (self, @selector (initWithComponentDescription:options:error:), descr, options, error); - - JuceAudioUnitv3Base* juceAU = JuceAudioUnitv3Base::create (self, descr, options, error); - - setThis (self, juceAU); - return self; - }); - - addMethod (@selector (dealloc), [] (id self, SEL) - { - if (! MessageManager::getInstance()->isThisTheMessageThread()) - { - WaitableEvent deletionEvent; - - struct AUDeleter : public CallbackMessage - { - AUDeleter (id selfToDelete, WaitableEvent& event) - : parentSelf (selfToDelete), parentDeletionEvent (event) - { - } - - void messageCallback() override - { - delete _this (parentSelf); - parentDeletionEvent.signal(); - } - - id parentSelf; - WaitableEvent& parentDeletionEvent; - }; - - (new AUDeleter (self, deletionEvent))->post(); - deletionEvent.wait (-1); - } - else - { - delete _this (self); - } - }); - - //============================================================================== - addMethod (@selector (reset), [] (id self, SEL) { return _this (self)->reset(); }); - - //============================================================================== - addMethod (@selector (currentPreset), [] (id self, SEL) { return _this (self)->getCurrentPreset(); }); - addMethod (@selector (setCurrentPreset:), [] (id self, SEL, AUAudioUnitPreset* preset) { return _this (self)->setCurrentPreset (preset); }); - addMethod (@selector (factoryPresets), [] (id self, SEL) { return _this (self)->getFactoryPresets(); }); - addMethod (@selector (fullState), [] (id self, SEL) { return _this (self)->getFullState(); }); - addMethod (@selector (setFullState:), [] (id self, SEL, NSDictionary* state) { return _this (self)->setFullState (state); }); - addMethod (@selector (parameterTree), [] (id self, SEL) { return _this (self)->getParameterTree(); }); - addMethod (@selector (parametersForOverviewWithCount:), [] (id self, SEL, NSInteger count) { return _this (self)->parametersForOverviewWithCount (static_cast (count)); }); - - //============================================================================== - addMethod (@selector (latency), [] (id self, SEL) { return _this (self)->getLatency(); }); - addMethod (@selector (tailTime), [] (id self, SEL) { return _this (self)->getTailTime(); }); - - //============================================================================== - addMethod (@selector (inputBusses), [] (id self, SEL) { return _this (self)->getInputBusses(); }); - addMethod (@selector (outputBusses), [] (id self, SEL) { return _this (self)->getOutputBusses(); }); - addMethod (@selector (channelCapabilities), [] (id self, SEL) { return _this (self)->getChannelCapabilities(); }); - addMethod (@selector (shouldChangeToFormat:forBus:), [] (id self, SEL, AVAudioFormat* format, AUAudioUnitBus* bus) { return _this (self)->shouldChangeToFormat (format, bus) ? YES : NO; }); - - //============================================================================== - addMethod (@selector (virtualMIDICableCount), [] (id self, SEL) { return _this (self)->getVirtualMIDICableCount(); }); - - JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wundeclared-selector") - addMethod (@selector (supportsMPE), [] (id self, SEL) { return _this (self)->getSupportsMPE() ? YES : NO; }); - JUCE_END_IGNORE_WARNINGS_GCC_LIKE - - if (@available (macOS 10.13, iOS 11.0, *)) - addMethod (@selector (MIDIOutputNames), [] (id self, SEL) { return _this (self)->getMIDIOutputNames(); }); - - //============================================================================== - addMethod (@selector (internalRenderBlock), [] (id self, SEL) { return _this (self)->getInternalRenderBlock(); }); - addMethod (@selector (canProcessInPlace), [] (id self, SEL) { return _this (self)->getCanProcessInPlace() ? YES : NO; }); - addMethod (@selector (isRenderingOffline), [] (id self, SEL) { return _this (self)->getRenderingOffline() ? YES : NO; }); - addMethod (@selector (setRenderingOffline:), [] (id self, SEL, BOOL renderingOffline) { return _this (self)->setRenderingOffline (renderingOffline); }); - addMethod (@selector (shouldBypassEffect), [] (id self, SEL) { return _this (self)->getShouldBypassEffect() ? YES : NO; }); - addMethod (@selector (setShouldBypassEffect:), [] (id self, SEL, BOOL shouldBypass) { return _this (self)->setShouldBypassEffect (shouldBypass); }); - addMethod (@selector (allocateRenderResourcesAndReturnError:), [] (id self, SEL, NSError** error) { return _this (self)->allocateRenderResourcesAndReturnError (error) ? YES : NO; }); - addMethod (@selector (deallocateRenderResources), [] (id self, SEL) { return _this (self)->deallocateRenderResources(); }); - - //============================================================================== - addMethod (@selector (contextName), [] (id self, SEL) { return _this (self)->getContextName(); }); - addMethod (@selector (setContextName:), [](id self, SEL, NSString* str) { return _this (self)->setContextName (str); }); - - //============================================================================== - if (@available (macOS 10.13, iOS 11.0, *)) - { - addMethod (@selector (supportedViewConfigurations:), [] (id self, SEL, NSArray* configs) { return _this (self)->getSupportedViewConfigurations (configs); }); - addMethod (@selector (selectViewConfiguration:), [] (id self, SEL, AUAudioUnitViewConfiguration* config) { return _this (self)->selectViewConfiguration (config); }); - } - - registerClass(); - } - - //============================================================================== - static JuceAudioUnitv3Base* _this (id self) { return getIvar (self, "cppObject"); } - static void setThis (id self, JuceAudioUnitv3Base* cpp) { object_setInstanceVariable (self, "cppObject", cpp); } - }; - - static JuceAudioUnitv3Base* create (AUAudioUnit*, AudioComponentDescription, AudioComponentInstantiationOptions, NSError**); - - //============================================================================== - static Class& getClass() - { - static Class result; - return result; - } - -protected: - AUAudioUnit* au; -}; - //============================================================================== //=========================== The actual AudioUnit ============================= //============================================================================== -class JuceAudioUnitv3 : public JuceAudioUnitv3Base, - public AudioProcessorListener, +class JuceAudioUnitv3 : public AudioProcessorListener, public AudioPlayHead, private AudioProcessorParameter::Listener { @@ -365,16 +115,24 @@ public: const AudioComponentDescription& descr, AudioComponentInstantiationOptions options, NSError** error) - : JuceAudioUnitv3Base (descr, options, error), + JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wobjc-method-access") + : au ([getClass().createInstance() initWithComponentDescription: descr + options: options + error: error + juceClass: this]), + JUCE_END_IGNORE_WARNINGS_GCC_LIKE processorHolder (processor) { init(); } JuceAudioUnitv3 (AUAudioUnit* audioUnit, AudioComponentDescription, AudioComponentInstantiationOptions, NSError**) - : JuceAudioUnitv3Base (audioUnit), + : au (audioUnit), processorHolder (new AudioProcessorHolder (createPluginFilterOfType (AudioProcessor::wrapperType_AudioUnitv3))) { + jassert (MessageManager::getInstance()->isThisTheMessageThread()); + initialiseJuce_GUI(); + init(); } @@ -401,7 +159,7 @@ public: inParameterChangedCallback = false; AudioProcessor& processor = getAudioProcessor(); - const AUAudioFrameCount maxFrames = [getAudioUnit() maximumFramesToRender]; + const AUAudioFrameCount maxFrames = [au maximumFramesToRender]; #ifdef JucePlugin_PreferredChannelConfigurations short configs[][2] = {JucePlugin_PreferredChannelConfigurations}; @@ -459,7 +217,7 @@ public: AudioProcessor& getAudioProcessor() const noexcept { return **processorHolder; } //============================================================================== - void reset() override + void reset() { midiMessages.clear(); lastTimeStamp.mSampleTime = std::numeric_limits::max(); @@ -467,27 +225,27 @@ public: } //============================================================================== - AUAudioUnitPreset* getCurrentPreset() override + AUAudioUnitPreset* getCurrentPreset() { return factoryPresets.getAtIndex (getAudioProcessor().getCurrentProgram()); } - void setCurrentPreset (AUAudioUnitPreset* preset) override + void setCurrentPreset (AUAudioUnitPreset* preset) { getAudioProcessor().setCurrentProgram (static_cast ([preset number])); } - NSArray* getFactoryPresets() override + NSArray* getFactoryPresets() { return factoryPresets.get(); } - NSDictionary* getFullState() override + NSDictionary* getFullState() { NSMutableDictionary* retval = [[NSMutableDictionary alloc] init]; { - NSDictionary* superRetval = JuceAudioUnitv3Base::getFullState(); + auto* superRetval = ObjCMsgSendSuper*> (au, @selector (fullState)); if (superRetval != nullptr) [retval addEntriesFromDictionary:superRetval]; @@ -518,7 +276,7 @@ public: return [retval autorelease]; } - void setFullState (NSDictionary* state) override + void setFullState (NSDictionary* state) { if (state == nullptr) return; @@ -530,7 +288,7 @@ public: [modifiedState removeObjectForKey: nsPresetKey]; [nsPresetKey release]; - JuceAudioUnitv3Base::setFullState (modifiedState); + ObjCMsgSendSuper (au, @selector (setFullState:), state); NSString* nsKey = [[NSString alloc] initWithUTF8String: JUCE_STATE_DICTIONARY_KEY]; NSObject* obj = [modifiedState objectForKey: nsKey]; @@ -558,12 +316,12 @@ public: [modifiedState release]; } - AUParameterTree* getParameterTree() override + AUParameterTree* getParameterTree() { return paramTree.get(); } - NSArray* parametersForOverviewWithCount (int count) override + NSArray* parametersForOverviewWithCount (int count) { const int n = static_cast ([overviewParams.get() count]); @@ -577,23 +335,23 @@ public: } //============================================================================== - NSTimeInterval getLatency() override + NSTimeInterval getLatency() { auto& p = getAudioProcessor(); return p.getLatencySamples() / p.getSampleRate(); } - NSTimeInterval getTailTime() override + NSTimeInterval getTailTime() { return getAudioProcessor().getTailLengthSeconds(); } //============================================================================== - AUAudioUnitBusArray* getInputBusses() override { return inputBusses.get(); } - AUAudioUnitBusArray* getOutputBusses() override { return outputBusses.get(); } - NSArray* getChannelCapabilities() override { return channelCapabilities.get(); } + AUAudioUnitBusArray* getInputBusses() { return inputBusses.get(); } + AUAudioUnitBusArray* getOutputBusses() { return outputBusses.get(); } + NSArray* getChannelCapabilities() { return channelCapabilities.get(); } - bool shouldChangeToFormat (AVAudioFormat* format, AUAudioUnitBus* auBus) override + bool shouldChangeToFormat (AVAudioFormat* format, AUAudioUnitBus* auBus) { const bool isInput = ([auBus busType] == AUAudioUnitBusTypeInput); const int busIdx = static_cast ([auBus index]); @@ -638,7 +396,7 @@ public: } //============================================================================== - int getVirtualMIDICableCount() override + int getVirtualMIDICableCount() { #if JucePlugin_WantsMidiInput return 1; @@ -647,12 +405,12 @@ public: #endif } - bool getSupportsMPE() override + bool getSupportsMPE() { return getAudioProcessor().supportsMPE(); } - NSArray* getMIDIOutputNames() override + NSArray* getMIDIOutputNames() { #if JucePlugin_ProducesMidiOutput return @[@"MIDI Out"]; @@ -662,9 +420,9 @@ public: } //============================================================================== - AUInternalRenderBlock getInternalRenderBlock() override { return internalRenderBlock; } - bool getRenderingOffline() override { return getAudioProcessor().isNonRealtime(); } - void setRenderingOffline (bool offline) override + AUInternalRenderBlock getInternalRenderBlock() { return internalRenderBlock; } + bool getRenderingOffline() { return getAudioProcessor().isNonRealtime(); } + void setRenderingOffline (bool offline) { auto& processor = getAudioProcessor(); auto isCurrentlyNonRealtime = processor.isNonRealtime(); @@ -678,25 +436,25 @@ public: } } - bool getShouldBypassEffect() override + bool getShouldBypassEffect() { if (bypassParam != nullptr) return (bypassParam->getValue() != 0.0f); - return JuceAudioUnitv3Base::getShouldBypassEffect(); + return (ObjCMsgSendSuper (au, @selector (shouldBypassEffect)) == YES); } - void setShouldBypassEffect (bool shouldBypass) override + void setShouldBypassEffect (bool shouldBypass) { if (bypassParam != nullptr) bypassParam->setValue (shouldBypass ? 1.0f : 0.0f); - JuceAudioUnitv3Base::setShouldBypassEffect (shouldBypass); + ObjCMsgSendSuper (au, @selector (setShouldBypassEffect:), shouldBypass ? YES : NO); } //============================================================================== - NSString* getContextName() const override { return juceStringToNS (contextName); } - void setContextName (NSString* str) override + NSString* getContextName() const { return juceStringToNS (contextName); } + void setContextName (NSString* str) { if (str != nullptr) { @@ -708,12 +466,12 @@ public: } //============================================================================== - bool allocateRenderResourcesAndReturnError (NSError **outError) override + bool allocateRenderResourcesAndReturnError (NSError **outError) { AudioProcessor& processor = getAudioProcessor(); - const AUAudioFrameCount maxFrames = [getAudioUnit() maximumFramesToRender]; + const AUAudioFrameCount maxFrames = [au maximumFramesToRender]; - if (! JuceAudioUnitv3Base::allocateRenderResourcesAndReturnError (outError)) + if (ObjCMsgSendSuper (au, @selector (allocateRenderResourcesAndReturnError:), outError) == NO) return false; if (outError != nullptr) @@ -726,7 +484,7 @@ public: const int n = AudioUnitHelpers::getBusCountForWrapper (processor, isInput); Array& channelSets = (isInput ? layouts.inputBuses : layouts.outputBuses); - AUAudioUnitBusArray* auBuses = (isInput ? [getAudioUnit() inputBusses] : [getAudioUnit() outputBusses]); + AUAudioUnitBusArray* auBuses = (isInput ? [au inputBusses] : [au outputBusses]); jassert ([auBuses count] == static_cast (n)); for (int busIdx = 0; busIdx < n; ++busIdx) @@ -797,8 +555,8 @@ public: midiMessages.ensureSize (2048); midiMessages.clear(); - hostMusicalContextCallback = [getAudioUnit() musicalContextBlock]; - hostTransportStateCallback = [getAudioUnit() transportStateBlock]; + hostMusicalContextCallback = [au musicalContextBlock]; + hostTransportStateCallback = [au transportStateBlock]; if (@available (macOS 10.13, iOS 11.0, *)) midiOutputEventBlock = [au MIDIOutputEventBlock]; @@ -808,7 +566,7 @@ public: return true; } - void deallocateRenderResources() override + void deallocateRenderResources() { midiOutputEventBlock = nullptr; @@ -823,49 +581,10 @@ public: mapper.release(); - JuceAudioUnitv3Base::deallocateRenderResources(); + ObjCMsgSendSuper (au, @selector (deallocateRenderResources)); } //============================================================================== - API_AVAILABLE (macos (10.13), ios (11.0)) - NSIndexSet* getSupportedViewConfigurations (NSArray* configs) override - { - auto supportedViewIndecies = [[NSMutableIndexSet alloc] init]; - auto n = [configs count]; - - if (auto* editor = getAudioProcessor().createEditorIfNeeded()) - { - // If you hit this assertion then your plug-in's editor is reporting that it doesn't support - // any host MIDI controller configurations! - jassert (editor->supportsHostMIDIControllerPresence (true) || editor->supportsHostMIDIControllerPresence (false)); - - for (auto i = 0u; i < n; ++i) - { - if (auto viewConfiguration = [configs objectAtIndex: i]) - { - if (editor->supportsHostMIDIControllerPresence ([viewConfiguration hostHasController] == YES)) - { - auto* constrainer = editor->getConstrainer(); - auto height = (int) [viewConfiguration height]; - auto width = (int) [viewConfiguration width]; - - if (height <= constrainer->getMaximumHeight() && height >= constrainer->getMinimumHeight() - && width <= constrainer->getMaximumWidth() && width >= constrainer->getMinimumWidth()) - [supportedViewIndecies addIndex: i]; - } - } - } - } - - return [supportedViewIndecies autorelease]; - } - - API_AVAILABLE (macos (10.13), ios (11.0)) - void selectViewConfiguration (AUAudioUnitViewConfiguration* config) override - { - processorHolder->viewConfiguration.reset (new AudioProcessorHolder::ViewConfig { [config width], [config height], [config hostHasController] == YES }); - } - struct ScopedKeyChange { ScopedKeyChange (AUAudioUnit* a, NSString* k) @@ -1029,7 +748,195 @@ public: } } + AUAudioUnit* getAudioUnit() const { return au; } + private: + struct Class : public ObjCClass + { + Class() : ObjCClass ("AUAudioUnit_") + { + addIvar ("cppObject"); + + JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wundeclared-selector") + addMethod (@selector (initWithComponentDescription:options:error:juceClass:), [] (id _self, + SEL, + AudioComponentDescription descr, + AudioComponentInstantiationOptions options, + NSError** error, + JuceAudioUnitv3* juceAU) + { + AUAudioUnit* self = _self; + + self = ObjCMsgSendSuper (self, @selector(initWithComponentDescription:options:error:), descr, options, error); + + setThis (self, juceAU); + return self; + }); + + JUCE_END_IGNORE_WARNINGS_GCC_LIKE + + addMethod (@selector (initWithComponentDescription:options:error:), [] (id _self, + SEL, + AudioComponentDescription descr, + AudioComponentInstantiationOptions options, + NSError** error) + { + AUAudioUnit* self = _self; + + self = ObjCMsgSendSuper (self, @selector (initWithComponentDescription:options:error:), descr, options, error); + + auto* juceAU = JuceAudioUnitv3::create (self, descr, options, error); + + setThis (self, juceAU); + return self; + }); + + addMethod (@selector (dealloc), [] (id self, SEL) + { + if (! MessageManager::getInstance()->isThisTheMessageThread()) + { + WaitableEvent deletionEvent; + + struct AUDeleter : public CallbackMessage + { + AUDeleter (id selfToDelete, WaitableEvent& event) + : parentSelf (selfToDelete), parentDeletionEvent (event) + { + } + + void messageCallback() override + { + delete _this (parentSelf); + parentDeletionEvent.signal(); + } + + id parentSelf; + WaitableEvent& parentDeletionEvent; + }; + + (new AUDeleter (self, deletionEvent))->post(); + deletionEvent.wait (-1); + } + else + { + delete _this (self); + } + }); + + //============================================================================== + addMethod (@selector (reset), [] (id self, SEL) { return _this (self)->reset(); }); + + //============================================================================== + addMethod (@selector (currentPreset), [] (id self, SEL) { return _this (self)->getCurrentPreset(); }); + addMethod (@selector (setCurrentPreset:), [] (id self, SEL, AUAudioUnitPreset* preset) { return _this (self)->setCurrentPreset (preset); }); + addMethod (@selector (factoryPresets), [] (id self, SEL) { return _this (self)->getFactoryPresets(); }); + addMethod (@selector (fullState), [] (id self, SEL) { return _this (self)->getFullState(); }); + addMethod (@selector (setFullState:), [] (id self, SEL, NSDictionary* state) { return _this (self)->setFullState (state); }); + addMethod (@selector (parameterTree), [] (id self, SEL) { return _this (self)->getParameterTree(); }); + addMethod (@selector (parametersForOverviewWithCount:), [] (id self, SEL, NSInteger count) { return _this (self)->parametersForOverviewWithCount (static_cast (count)); }); + + //============================================================================== + addMethod (@selector (latency), [] (id self, SEL) { return _this (self)->getLatency(); }); + addMethod (@selector (tailTime), [] (id self, SEL) { return _this (self)->getTailTime(); }); + + //============================================================================== + addMethod (@selector (inputBusses), [] (id self, SEL) { return _this (self)->getInputBusses(); }); + addMethod (@selector (outputBusses), [] (id self, SEL) { return _this (self)->getOutputBusses(); }); + addMethod (@selector (channelCapabilities), [] (id self, SEL) { return _this (self)->getChannelCapabilities(); }); + addMethod (@selector (shouldChangeToFormat:forBus:), [] (id self, SEL, AVAudioFormat* format, AUAudioUnitBus* bus) { return _this (self)->shouldChangeToFormat (format, bus) ? YES : NO; }); + + //============================================================================== + addMethod (@selector (virtualMIDICableCount), [] (id self, SEL) { return _this (self)->getVirtualMIDICableCount(); }); + + JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wundeclared-selector") + addMethod (@selector (supportsMPE), [] (id self, SEL) { return _this (self)->getSupportsMPE() ? YES : NO; }); + JUCE_END_IGNORE_WARNINGS_GCC_LIKE + + if (@available (macOS 10.13, iOS 11.0, *)) + addMethod (@selector (MIDIOutputNames), [] (id self, SEL) { return _this (self)->getMIDIOutputNames(); }); + + //============================================================================== + addMethod (@selector (internalRenderBlock), [] (id self, SEL) { return _this (self)->getInternalRenderBlock(); }); + addMethod (@selector (canProcessInPlace), [] (id, SEL) { return NO; }); + addMethod (@selector (isRenderingOffline), [] (id self, SEL) { return _this (self)->getRenderingOffline() ? YES : NO; }); + addMethod (@selector (setRenderingOffline:), [] (id self, SEL, BOOL renderingOffline) { return _this (self)->setRenderingOffline (renderingOffline); }); + addMethod (@selector (shouldBypassEffect), [] (id self, SEL) { return _this (self)->getShouldBypassEffect() ? YES : NO; }); + addMethod (@selector (setShouldBypassEffect:), [] (id self, SEL, BOOL shouldBypass) { return _this (self)->setShouldBypassEffect (shouldBypass); }); + addMethod (@selector (allocateRenderResourcesAndReturnError:), [] (id self, SEL, NSError** error) { return _this (self)->allocateRenderResourcesAndReturnError (error) ? YES : NO; }); + addMethod (@selector (deallocateRenderResources), [] (id self, SEL) { return _this (self)->deallocateRenderResources(); }); + + //============================================================================== + addMethod (@selector (contextName), [] (id self, SEL) { return _this (self)->getContextName(); }); + addMethod (@selector (setContextName:), [](id self, SEL, NSString* str) { return _this (self)->setContextName (str); }); + + //============================================================================== + if (@available (macOS 10.13, iOS 11.0, *)) + { + addMethod (@selector (supportedViewConfigurations:), [] (id self, SEL, NSArray* configs) + { + auto supportedViewIndices = [[NSMutableIndexSet alloc] init]; + auto n = [configs count]; + + if (auto* editor = _this (self)->getAudioProcessor().createEditorIfNeeded()) + { + // If you hit this assertion then your plug-in's editor is reporting that it doesn't support + // any host MIDI controller configurations! + jassert (editor->supportsHostMIDIControllerPresence (true) || editor->supportsHostMIDIControllerPresence (false)); + + for (auto i = 0u; i < n; ++i) + { + if (auto viewConfiguration = [configs objectAtIndex: i]) + { + if (editor->supportsHostMIDIControllerPresence ([viewConfiguration hostHasController] == YES)) + { + auto* constrainer = editor->getConstrainer(); + auto height = (int) [viewConfiguration height]; + auto width = (int) [viewConfiguration width]; + + const auto maxLimits = std::numeric_limits::max() / 2; + const Rectangle requestedBounds { width, height }; + auto modifiedBounds = requestedBounds; + constrainer->checkBounds (modifiedBounds, editor->getBounds().withZeroOrigin(), { maxLimits, maxLimits }, false, false, false, false); + + if (modifiedBounds == requestedBounds) + [supportedViewIndices addIndex: i]; + } + } + } + } + + return [supportedViewIndices autorelease]; + }); + + addMethod (@selector (selectViewConfiguration:), [] (id self, SEL, AUAudioUnitViewConfiguration* config) + { + _this (self)->processorHolder->viewConfiguration.reset (new AudioProcessorHolder::ViewConfig { [config width], [config height], [config hostHasController] == YES }); + }); + } + + registerClass(); + } + + //============================================================================== + static JuceAudioUnitv3* _this (id self) { return getIvar (self, "cppObject"); } + static void setThis (id self, JuceAudioUnitv3* cpp) { object_setInstanceVariable (self, "cppObject", cpp); } + }; + + static JuceAudioUnitv3* create (AUAudioUnit* audioUnit, AudioComponentDescription descr, AudioComponentInstantiationOptions options, NSError** error) + { + PluginHostType::jucePlugInClientCurrentWrapperType = AudioProcessor::wrapperType_AudioUnitv3; + return new JuceAudioUnitv3 (audioUnit, descr, options, error); + } + + //============================================================================== + static Class& getClass() + { + static Class result; + return result; + } + //============================================================================== struct BusBuffer { @@ -1415,7 +1322,7 @@ private: busBuffers.clear(); const int n = AudioUnitHelpers::getBusCountForWrapper (getAudioProcessor(), isInput); - const AUAudioFrameCount maxFrames = [getAudioUnit() maximumFramesToRender]; + const AUAudioFrameCount maxFrames = [au maximumFramesToRender]; for (int busIdx = 0; busIdx < n; ++busIdx) busBuffers.add (new BusBuffer ([(isInput ? inputBusses.get() : outputBusses.get()) objectAtIndexedSubscript: static_cast (busIdx)], @@ -1685,7 +1592,7 @@ private: // this is only ever called for the bypass parameter void parameterValueChanged (int, float newValue) override { - JuceAudioUnitv3Base::setShouldBypassEffect (newValue != 0.0f); + JuceAudioUnitv3::setShouldBypassEffect (newValue != 0.0f); } void parameterGestureChanged (int, bool) override {} @@ -1723,8 +1630,9 @@ private: } //============================================================================== - static const double kDefaultSampleRate; + static constexpr double kDefaultSampleRate = 44100.0; + AUAudioUnit* au; AudioProcessorHolder::Ptr processorHolder; int totalInChannels, totalOutChannels; @@ -1782,14 +1690,6 @@ private: AudioProcessorParameter* bypassParam = nullptr; }; -const double JuceAudioUnitv3::kDefaultSampleRate = 44100.0; - -JuceAudioUnitv3Base* JuceAudioUnitv3Base::create (AUAudioUnit* audioUnit, AudioComponentDescription descr, AudioComponentInstantiationOptions options, NSError** error) -{ - PluginHostType::jucePlugInClientCurrentWrapperType = AudioProcessor::wrapperType_AudioUnitv3; - return new JuceAudioUnitv3 (audioUnit, descr, options, error); -} - #if JUCE_IOS namespace juce {