upgrade to JUCE 5.4.3. Remove (probably) unused JUCE modules. Remove VST2 target (it's been end-of-life'd by Steinberg and by JUCE)
This commit is contained in:
		@ -41,6 +41,9 @@
 | 
			
		||||
 #pragma clang diagnostic ignored "-Wnon-virtual-dtor"
 | 
			
		||||
 #pragma clang diagnostic ignored "-Wsign-conversion"
 | 
			
		||||
 #pragma clang diagnostic ignored "-Wextra-semi"
 | 
			
		||||
 #if __has_warning("-Wpragma-pack")
 | 
			
		||||
  #pragma clang diagnostic ignored "-Wpragma-pack"
 | 
			
		||||
 #endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef _MSC_VER
 | 
			
		||||
@ -162,22 +165,53 @@ namespace AAXClasses
 | 
			
		||||
 | 
			
		||||
    static AAXChannelStreamOrder aaxChannelOrder[] =
 | 
			
		||||
    {
 | 
			
		||||
        { AAX_eStemFormat_Mono,     { AudioChannelSet::centre, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown } },
 | 
			
		||||
        { AAX_eStemFormat_Stereo,   { AudioChannelSet::left, AudioChannelSet::right, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown } },
 | 
			
		||||
        { AAX_eStemFormat_LCR,      { AudioChannelSet::left, AudioChannelSet::centre, AudioChannelSet::right, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown } },
 | 
			
		||||
        { AAX_eStemFormat_LCRS,     { AudioChannelSet::left, AudioChannelSet::centre, AudioChannelSet::right, AudioChannelSet::centreSurround, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown } },
 | 
			
		||||
        { AAX_eStemFormat_Quad,     { AudioChannelSet::left, AudioChannelSet::right,  AudioChannelSet::leftSurround, AudioChannelSet::rightSurround, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown } },
 | 
			
		||||
        { AAX_eStemFormat_5_0,      { AudioChannelSet::left, AudioChannelSet::centre, AudioChannelSet::right, AudioChannelSet::leftSurround, AudioChannelSet::rightSurround, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown } },
 | 
			
		||||
        { AAX_eStemFormat_5_1,      { AudioChannelSet::left, AudioChannelSet::centre, AudioChannelSet::right, AudioChannelSet::leftSurround, AudioChannelSet::rightSurround, AudioChannelSet::LFE, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown } },
 | 
			
		||||
        { AAX_eStemFormat_6_0,      { AudioChannelSet::left, AudioChannelSet::centre, AudioChannelSet::right, AudioChannelSet::leftSurround, AudioChannelSet::centreSurround, AudioChannelSet::rightSurround, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown } },
 | 
			
		||||
        { AAX_eStemFormat_6_1,      { AudioChannelSet::left, AudioChannelSet::centre, AudioChannelSet::right, AudioChannelSet::leftSurround, AudioChannelSet::centreSurround, AudioChannelSet::rightSurround, AudioChannelSet::LFE, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown } },
 | 
			
		||||
        { AAX_eStemFormat_7_0_SDDS, { AudioChannelSet::left, AudioChannelSet::leftCentre, AudioChannelSet::centre, AudioChannelSet::rightCentre, AudioChannelSet::right, AudioChannelSet::leftSurround, AudioChannelSet::rightSurround, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown } },
 | 
			
		||||
        { AAX_eStemFormat_7_0_DTS,  { AudioChannelSet::left, AudioChannelSet::centre, AudioChannelSet::right, AudioChannelSet::leftSurroundSide, AudioChannelSet::rightSurroundSide, AudioChannelSet::leftSurroundRear, AudioChannelSet::rightSurroundRear, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown } },
 | 
			
		||||
        { AAX_eStemFormat_7_1_SDDS, { AudioChannelSet::left, AudioChannelSet::leftCentre, AudioChannelSet::centre, AudioChannelSet::rightCentre, AudioChannelSet::right, AudioChannelSet::leftSurround, AudioChannelSet::rightSurround, AudioChannelSet::LFE, AudioChannelSet::unknown, AudioChannelSet::unknown } },
 | 
			
		||||
        { AAX_eStemFormat_7_1_DTS,  { AudioChannelSet::left, AudioChannelSet::centre, AudioChannelSet::right, AudioChannelSet::leftSurroundSide, AudioChannelSet::rightSurroundSide, AudioChannelSet::leftSurroundRear, AudioChannelSet::rightSurroundRear, AudioChannelSet::LFE, AudioChannelSet::unknown, AudioChannelSet::unknown } },
 | 
			
		||||
        { AAX_eStemFormat_7_0_2,    { AudioChannelSet::left, AudioChannelSet::centre, AudioChannelSet::right, AudioChannelSet::leftSurroundSide, AudioChannelSet::rightSurroundSide, AudioChannelSet::leftSurroundRear, AudioChannelSet::rightSurroundRear, AudioChannelSet::topSideLeft, AudioChannelSet::topSideRight, AudioChannelSet::unknown } },
 | 
			
		||||
        { AAX_eStemFormat_7_1_2,    { AudioChannelSet::left, AudioChannelSet::centre, AudioChannelSet::right, AudioChannelSet::leftSurroundSide, AudioChannelSet::rightSurroundSide, AudioChannelSet::leftSurroundRear, AudioChannelSet::rightSurroundRear, AudioChannelSet::LFE, AudioChannelSet::topSideLeft, AudioChannelSet::topSideRight } },
 | 
			
		||||
        { AAX_eStemFormat_None,     { AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown } },
 | 
			
		||||
        { AAX_eStemFormat_Mono,     { AudioChannelSet::centre, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown,
 | 
			
		||||
                                      AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown } },
 | 
			
		||||
 | 
			
		||||
        { AAX_eStemFormat_Stereo,   { AudioChannelSet::left, AudioChannelSet::right, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown,
 | 
			
		||||
                                      AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown } },
 | 
			
		||||
 | 
			
		||||
        { AAX_eStemFormat_LCR,      { AudioChannelSet::left, AudioChannelSet::centre, AudioChannelSet::right, AudioChannelSet::unknown, AudioChannelSet::unknown,
 | 
			
		||||
                                      AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown } },
 | 
			
		||||
 | 
			
		||||
        { AAX_eStemFormat_LCRS,     { AudioChannelSet::left, AudioChannelSet::centre, AudioChannelSet::right, AudioChannelSet::centreSurround, AudioChannelSet::unknown,
 | 
			
		||||
                                      AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown } },
 | 
			
		||||
 | 
			
		||||
        { AAX_eStemFormat_Quad,     { AudioChannelSet::left, AudioChannelSet::right,  AudioChannelSet::leftSurround, AudioChannelSet::rightSurround, AudioChannelSet::unknown,
 | 
			
		||||
                                      AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown } },
 | 
			
		||||
 | 
			
		||||
        { AAX_eStemFormat_5_0,      { AudioChannelSet::left, AudioChannelSet::centre, AudioChannelSet::right, AudioChannelSet::leftSurround, AudioChannelSet::rightSurround,
 | 
			
		||||
                                      AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown } },
 | 
			
		||||
 | 
			
		||||
        { AAX_eStemFormat_5_1,      { AudioChannelSet::left, AudioChannelSet::centre, AudioChannelSet::right, AudioChannelSet::leftSurround, AudioChannelSet::rightSurround,
 | 
			
		||||
                                      AudioChannelSet::LFE, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown } },
 | 
			
		||||
 | 
			
		||||
        { AAX_eStemFormat_6_0,      { AudioChannelSet::left, AudioChannelSet::centre, AudioChannelSet::right, AudioChannelSet::leftSurround, AudioChannelSet::centreSurround,
 | 
			
		||||
                                      AudioChannelSet::rightSurround, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown } },
 | 
			
		||||
 | 
			
		||||
        { AAX_eStemFormat_6_1,      { AudioChannelSet::left, AudioChannelSet::centre, AudioChannelSet::right, AudioChannelSet::leftSurround, AudioChannelSet::centreSurround,
 | 
			
		||||
                                      AudioChannelSet::rightSurround, AudioChannelSet::LFE, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown } },
 | 
			
		||||
 | 
			
		||||
        { AAX_eStemFormat_7_0_SDDS, { AudioChannelSet::left, AudioChannelSet::leftCentre, AudioChannelSet::centre, AudioChannelSet::rightCentre, AudioChannelSet::right,
 | 
			
		||||
                                      AudioChannelSet::leftSurround, AudioChannelSet::rightSurround, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown } },
 | 
			
		||||
 | 
			
		||||
        { AAX_eStemFormat_7_0_DTS,  { AudioChannelSet::left, AudioChannelSet::centre, AudioChannelSet::right, AudioChannelSet::leftSurroundSide, AudioChannelSet::rightSurroundSide,
 | 
			
		||||
                                      AudioChannelSet::leftSurroundRear, AudioChannelSet::rightSurroundRear, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown } },
 | 
			
		||||
 | 
			
		||||
        { AAX_eStemFormat_7_1_SDDS, { AudioChannelSet::left, AudioChannelSet::leftCentre, AudioChannelSet::centre, AudioChannelSet::rightCentre, AudioChannelSet::right,
 | 
			
		||||
                                      AudioChannelSet::leftSurround, AudioChannelSet::rightSurround, AudioChannelSet::LFE, AudioChannelSet::unknown, AudioChannelSet::unknown } },
 | 
			
		||||
 | 
			
		||||
        { AAX_eStemFormat_7_1_DTS,  { AudioChannelSet::left, AudioChannelSet::centre, AudioChannelSet::right, AudioChannelSet::leftSurroundSide, AudioChannelSet::rightSurroundSide,
 | 
			
		||||
                                      AudioChannelSet::leftSurroundRear, AudioChannelSet::rightSurroundRear, AudioChannelSet::LFE, AudioChannelSet::unknown, AudioChannelSet::unknown } },
 | 
			
		||||
 | 
			
		||||
        { AAX_eStemFormat_7_0_2,    { AudioChannelSet::left, AudioChannelSet::centre, AudioChannelSet::right, AudioChannelSet::leftSurroundSide, AudioChannelSet::rightSurroundSide,
 | 
			
		||||
                                      AudioChannelSet::leftSurroundRear, AudioChannelSet::rightSurroundRear, AudioChannelSet::topSideLeft, AudioChannelSet::topSideRight, AudioChannelSet::unknown } },
 | 
			
		||||
 | 
			
		||||
        { AAX_eStemFormat_7_1_2,    { AudioChannelSet::left, AudioChannelSet::centre, AudioChannelSet::right, AudioChannelSet::leftSurroundSide, AudioChannelSet::rightSurroundSide,
 | 
			
		||||
                                      AudioChannelSet::leftSurroundRear, AudioChannelSet::rightSurroundRear, AudioChannelSet::LFE, AudioChannelSet::topSideLeft, AudioChannelSet::topSideRight } },
 | 
			
		||||
 | 
			
		||||
        { AAX_eStemFormat_None,     { AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown,
 | 
			
		||||
                                      AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown, AudioChannelSet::unknown } },
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    static AAX_EStemFormat aaxFormats[] =
 | 
			
		||||
@ -624,6 +658,8 @@ namespace AAXClasses
 | 
			
		||||
 | 
			
		||||
    static void AAX_CALLBACK algorithmProcessCallback (JUCEAlgorithmContext* const instancesBegin[], const void* const instancesEnd);
 | 
			
		||||
 | 
			
		||||
    static Array<JuceAAX_Processor*> activeProcessors;
 | 
			
		||||
 | 
			
		||||
    //==============================================================================
 | 
			
		||||
    class JuceAAX_Processor   : public AAX_CEffectParameters,
 | 
			
		||||
                                public juce::AudioPlayHead,
 | 
			
		||||
@ -642,11 +678,30 @@ namespace AAXClasses
 | 
			
		||||
            rebuildChannelMapArrays();
 | 
			
		||||
 | 
			
		||||
            AAX_CEffectParameters::GetNumberOfChunks (&juceChunkIndex);
 | 
			
		||||
            activeProcessors.add (this);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ~JuceAAX_Processor()
 | 
			
		||||
        {
 | 
			
		||||
            activeProcessors.removeAllInstancesOf (this);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        static AAX_CEffectParameters* AAX_CALLBACK Create()
 | 
			
		||||
        {
 | 
			
		||||
            PluginHostType::jucePlugInClientCurrentWrapperType = AudioProcessor::wrapperType_AAX;
 | 
			
		||||
 | 
			
		||||
            if (PluginHostType::jucePlugInIsRunningInAudioSuiteFn == nullptr)
 | 
			
		||||
            {
 | 
			
		||||
                PluginHostType::jucePlugInIsRunningInAudioSuiteFn = [] (AudioProcessor& processor)
 | 
			
		||||
                {
 | 
			
		||||
                    for (auto* p : activeProcessors)
 | 
			
		||||
                        if (&p->getPluginInstance() == &processor)
 | 
			
		||||
                            return p->isInAudioSuite();
 | 
			
		||||
 | 
			
		||||
                    return false;
 | 
			
		||||
                };
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return new JuceAAX_Processor();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -849,7 +904,7 @@ namespace AAXClasses
 | 
			
		||||
        AAX_Result GetParameterNumberofSteps (AAX_CParamID paramID, int32_t* result) const
 | 
			
		||||
        {
 | 
			
		||||
            if (auto* param = getParameterFromID (paramID))
 | 
			
		||||
                *result = param->getNumSteps();
 | 
			
		||||
                *result = getSafeNumberOfParameterSteps (*param);
 | 
			
		||||
 | 
			
		||||
            return AAX_SUCCESS;
 | 
			
		||||
        }
 | 
			
		||||
@ -1091,7 +1146,9 @@ namespace AAXClasses
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                isSuspended = true;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (isSuspended)
 | 
			
		||||
            {
 | 
			
		||||
@ -1311,6 +1368,14 @@ namespace AAXClasses
 | 
			
		||||
            return foundValid;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        bool isInAudioSuite()
 | 
			
		||||
        {
 | 
			
		||||
            AAX_CBoolean res;
 | 
			
		||||
            Controller()->GetIsAudioSuite (&res);
 | 
			
		||||
 | 
			
		||||
            return res;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
        friend class JuceAAX_GUI;
 | 
			
		||||
        friend void AAX_CALLBACK AAXClasses::algorithmProcessCallback (JUCEAlgorithmContext* const instancesBegin[], const void* const instancesEnd);
 | 
			
		||||
@ -1405,6 +1470,14 @@ namespace AAXClasses
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Some older Pro Tools control surfaces (EUCON [PT version 12.4] and
 | 
			
		||||
        // Avid S6 before version 2.1) cannot cope with a large number of
 | 
			
		||||
        // parameter steps.
 | 
			
		||||
        static int32_t getSafeNumberOfParameterSteps (const AudioProcessorParameter& param)
 | 
			
		||||
        {
 | 
			
		||||
            return jmin (param.getNumSteps(), 2048);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void addAudioProcessorParameters()
 | 
			
		||||
        {
 | 
			
		||||
            auto& audioProcessor = getPluginInstance();
 | 
			
		||||
@ -1446,7 +1519,6 @@ namespace AAXClasses
 | 
			
		||||
                aaxParamIDs.add (paramID);
 | 
			
		||||
                auto aaxParamID = aaxParamIDs.getReference (parameterIndex++).getCharPointer();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                paramMap.set (AAXClasses::getAAXParamHash (aaxParamID), juceParam);
 | 
			
		||||
 | 
			
		||||
                // is this a meter?
 | 
			
		||||
@ -1465,7 +1537,7 @@ namespace AAXClasses
 | 
			
		||||
 | 
			
		||||
                parameter->AddShortenedName (juceParam->getName (4).toRawUTF8());
 | 
			
		||||
 | 
			
		||||
                auto parameterNumSteps = juceParam->getNumSteps();
 | 
			
		||||
                auto parameterNumSteps = getSafeNumberOfParameterSteps (*juceParam);
 | 
			
		||||
                parameter->SetNumberOfSteps ((uint32_t) parameterNumSteps);
 | 
			
		||||
 | 
			
		||||
               #if JUCE_FORCE_LEGACY_PARAMETER_AUTOMATION_TYPE
 | 
			
		||||
@ -1492,10 +1564,6 @@ namespace AAXClasses
 | 
			
		||||
        bool getMainBusFormats (AudioChannelSet& inputSet, AudioChannelSet& outputSet)
 | 
			
		||||
        {
 | 
			
		||||
            auto& audioProcessor = getPluginInstance();
 | 
			
		||||
           #if ! JucePlugin_IsMidiEffect
 | 
			
		||||
            auto inputBuses  = audioProcessor.getBusCount (true);
 | 
			
		||||
            auto outputBuses = audioProcessor.getBusCount (false);
 | 
			
		||||
           #endif
 | 
			
		||||
 | 
			
		||||
           #if JucePlugin_IsMidiEffect
 | 
			
		||||
            // MIDI effect plug-ins do not support any audio channels
 | 
			
		||||
@ -1505,24 +1573,25 @@ namespace AAXClasses
 | 
			
		||||
            inputSet = outputSet = AudioChannelSet();
 | 
			
		||||
            return true;
 | 
			
		||||
           #else
 | 
			
		||||
            auto inputBuses  = audioProcessor.getBusCount (true);
 | 
			
		||||
            auto outputBuses = audioProcessor.getBusCount (false);
 | 
			
		||||
 | 
			
		||||
            AAX_EStemFormat inputStemFormat = AAX_eStemFormat_None;
 | 
			
		||||
            check (Controller()->GetInputStemFormat (&inputStemFormat));
 | 
			
		||||
 | 
			
		||||
            AAX_EStemFormat outputStemFormat = AAX_eStemFormat_None;
 | 
			
		||||
            check (Controller()->GetOutputStemFormat (&outputStemFormat));
 | 
			
		||||
 | 
			
		||||
           #if JucePlugin_IsSynth
 | 
			
		||||
            if (inputBuses == 0)
 | 
			
		||||
                inputStemFormat = AAX_eStemFormat_None;
 | 
			
		||||
           #endif
 | 
			
		||||
            #if JucePlugin_IsSynth
 | 
			
		||||
             if (inputBuses == 0)
 | 
			
		||||
                 inputStemFormat = AAX_eStemFormat_None;
 | 
			
		||||
            #endif
 | 
			
		||||
 | 
			
		||||
            inputSet  = (inputBuses  > 0 ? channelSetFromStemFormat (inputStemFormat,  false) : AudioChannelSet());
 | 
			
		||||
            outputSet = (outputBuses > 0 ? channelSetFromStemFormat (outputStemFormat, false) : AudioChannelSet());
 | 
			
		||||
 | 
			
		||||
            if (  (inputSet  == AudioChannelSet::disabled() && inputStemFormat  != AAX_eStemFormat_None)
 | 
			
		||||
                || (outputSet == AudioChannelSet::disabled() && outputStemFormat != AAX_eStemFormat_None)
 | 
			
		||||
                || (inputSet  != AudioChannelSet::disabled() && inputBuses  == 0)
 | 
			
		||||
                || (outputSet != AudioChannelSet::disabled() && outputBuses == 0))
 | 
			
		||||
            if ((inputSet == AudioChannelSet::disabled() && inputStemFormat != AAX_eStemFormat_None) || (outputSet == AudioChannelSet::disabled() && outputStemFormat != AAX_eStemFormat_None)
 | 
			
		||||
                || (inputSet != AudioChannelSet::disabled() && inputBuses == 0) || (outputSet != AudioChannelSet::disabled() && outputBuses == 0))
 | 
			
		||||
                return false;
 | 
			
		||||
 | 
			
		||||
            return true;
 | 
			
		||||
@ -1577,6 +1646,27 @@ namespace AAXClasses
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (isInAudioSuite())
 | 
			
		||||
            {
 | 
			
		||||
                // AudioSuite doesnt support multiple output buses
 | 
			
		||||
                for (int i = 1; i < newLayout.outputBuses.size(); ++i)
 | 
			
		||||
                    newLayout.outputBuses.getReference (i) = AudioChannelSet::disabled();
 | 
			
		||||
 | 
			
		||||
                if (! audioProcessor.checkBusesLayoutSupported (newLayout))
 | 
			
		||||
                {
 | 
			
		||||
                    // your plug-in needs to support a single output bus if running in AudioSuite
 | 
			
		||||
                    jassertfalse;
 | 
			
		||||
 | 
			
		||||
                    if (isPrepared)
 | 
			
		||||
                    {
 | 
			
		||||
                        isPrepared = false;
 | 
			
		||||
                        audioProcessor.releaseResources();
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    return AAX_ERROR_UNIMPLEMENTED;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            const bool layoutChanged = (oldLayout != newLayout);
 | 
			
		||||
 | 
			
		||||
            if (layoutChanged)
 | 
			
		||||
@ -1607,6 +1697,9 @@ namespace AAXClasses
 | 
			
		||||
                audioProcessor.prepareToPlay (sampleRate, lastBufferSize);
 | 
			
		||||
                maxBufferSize = lastBufferSize;
 | 
			
		||||
 | 
			
		||||
                midiBuffer.ensureSize (2048);
 | 
			
		||||
                midiBuffer.clear();
 | 
			
		||||
 | 
			
		||||
                sideChainBuffer.calloc (static_cast<size_t> (maxBufferSize));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@ -1704,6 +1797,103 @@ namespace AAXClasses
 | 
			
		||||
            updateSidechainState();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //==============================================================================
 | 
			
		||||
        static AudioProcessor::CurveData::Type aaxCurveTypeToJUCE (AAX_CTypeID type) noexcept
 | 
			
		||||
        {
 | 
			
		||||
            switch (type)
 | 
			
		||||
            {
 | 
			
		||||
            case AAX_eCurveType_EQ:              return AudioProcessor::CurveData::Type::EQ;
 | 
			
		||||
            case AAX_eCurveType_Dynamics:        return AudioProcessor::CurveData::Type::Dynamics;
 | 
			
		||||
            case AAX_eCurveType_Reduction:       return AudioProcessor::CurveData::Type::GainReduction;
 | 
			
		||||
            default:  break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return AudioProcessor::CurveData::Type::Unknown;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        uint32_t getAAXMeterIdForParamId (const String& paramID) const noexcept
 | 
			
		||||
        {
 | 
			
		||||
            int idx;
 | 
			
		||||
 | 
			
		||||
            for (idx = 0; idx < aaxMeters.size(); ++idx)
 | 
			
		||||
                if (LegacyAudioParameter::getParamID (aaxMeters[idx], false) == paramID)
 | 
			
		||||
                    break;
 | 
			
		||||
 | 
			
		||||
            // you sepecified a parameter id in your curve but the parameter does not have the meter
 | 
			
		||||
            // category
 | 
			
		||||
            jassert (idx < aaxMeters.size());
 | 
			
		||||
            return 'Metr' + static_cast<AAX_CTypeID> (idx);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //==============================================================================
 | 
			
		||||
        AAX_Result GetCurveData (AAX_CTypeID iCurveType, const float * iValues, uint32_t iNumValues, float * oValues ) const override
 | 
			
		||||
        {
 | 
			
		||||
            auto curveType = aaxCurveTypeToJUCE (iCurveType);
 | 
			
		||||
 | 
			
		||||
            if (curveType != AudioProcessor::CurveData::Type::Unknown)
 | 
			
		||||
            {
 | 
			
		||||
                auto& audioProcessor = getPluginInstance();
 | 
			
		||||
                auto curve = audioProcessor.getResponseCurve (curveType);
 | 
			
		||||
 | 
			
		||||
                if (curve.curve)
 | 
			
		||||
                {
 | 
			
		||||
                    if (oValues != nullptr && iValues != nullptr)
 | 
			
		||||
                    {
 | 
			
		||||
                        for (uint32_t i = 0; i < iNumValues; ++i)
 | 
			
		||||
                            oValues[i] = curve.curve (iValues[i]);
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    return AAX_SUCCESS;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return AAX_ERROR_UNIMPLEMENTED;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        AAX_Result GetCurveDataMeterIds (AAX_CTypeID iCurveType, uint32_t *oXMeterId, uint32_t *oYMeterId)  const override
 | 
			
		||||
        {
 | 
			
		||||
            auto curveType = aaxCurveTypeToJUCE (iCurveType);
 | 
			
		||||
 | 
			
		||||
            if (curveType != AudioProcessor::CurveData::Type::Unknown)
 | 
			
		||||
            {
 | 
			
		||||
                auto& audioProcessor = getPluginInstance();
 | 
			
		||||
                auto curve = audioProcessor.getResponseCurve (curveType);
 | 
			
		||||
 | 
			
		||||
                if (curve.curve && curve.xMeterID.isNotEmpty() && curve.yMeterID.isNotEmpty())
 | 
			
		||||
                {
 | 
			
		||||
                    if (oXMeterId != nullptr) *oXMeterId = getAAXMeterIdForParamId (curve.xMeterID);
 | 
			
		||||
                    if (oYMeterId != nullptr) *oYMeterId = getAAXMeterIdForParamId (curve.yMeterID);
 | 
			
		||||
 | 
			
		||||
                    return AAX_SUCCESS;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return AAX_ERROR_UNIMPLEMENTED;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        AAX_Result GetCurveDataDisplayRange (AAX_CTypeID iCurveType, float *oXMin, float *oXMax, float *oYMin, float *oYMax) const override
 | 
			
		||||
        {
 | 
			
		||||
            auto curveType = aaxCurveTypeToJUCE (iCurveType);
 | 
			
		||||
 | 
			
		||||
            if (curveType != AudioProcessor::CurveData::Type::Unknown)
 | 
			
		||||
            {
 | 
			
		||||
                auto& audioProcessor = getPluginInstance();
 | 
			
		||||
                auto curve = audioProcessor.getResponseCurve (curveType);
 | 
			
		||||
 | 
			
		||||
                if (curve.curve)
 | 
			
		||||
                {
 | 
			
		||||
                    if (oXMin != nullptr) *oXMin = curve.xRange.getStart();
 | 
			
		||||
                    if (oXMax != nullptr) *oXMax = curve.xRange.getEnd();
 | 
			
		||||
                    if (oYMin != nullptr) *oYMin = curve.yRange.getStart();
 | 
			
		||||
                    if (oYMax != nullptr) *oYMax = curve.yRange.getEnd();
 | 
			
		||||
 | 
			
		||||
                    return AAX_SUCCESS;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return AAX_ERROR_UNIMPLEMENTED;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //==============================================================================
 | 
			
		||||
        inline int getParamIndexFromID (AAX_CParamID paramID) const noexcept
 | 
			
		||||
        {
 | 
			
		||||
@ -1792,7 +1982,7 @@ namespace AAXClasses
 | 
			
		||||
        // and the size of the data returned. To avoid generating
 | 
			
		||||
        // it again in GetChunk, we need to store it somewhere.
 | 
			
		||||
        // However, as GetChunkSize and GetChunk can be called
 | 
			
		||||
        // on different threads, we store it in thread dependant storage
 | 
			
		||||
        // on different threads, we store it in thread dependent storage
 | 
			
		||||
        // in a hash map with the thread id as a key.
 | 
			
		||||
        mutable ThreadLocalValue<ChunkMemoryBlock> perThreadFilterData;
 | 
			
		||||
        CriticalSection perThreadDataLock;
 | 
			
		||||
@ -1997,11 +2187,17 @@ namespace AAXClasses
 | 
			
		||||
            check (desc.AddSideChainIn (JUCEAlgorithmIDs::sideChainBuffers));
 | 
			
		||||
            properties->AddProperty (AAX_eProperty_SupportsSideChainInput, true);
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            // AAX does not allow there to be any gaps in the fields of the algorithm context structure
 | 
			
		||||
            // so just add a dummy one here if there aren't any side chains
 | 
			
		||||
            check (desc.AddPrivateData (JUCEAlgorithmIDs::sideChainBuffers, sizeof (uintptr_t)));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        auto maxAuxBuses = jmax (0, jmin (15, fullLayout.outputBuses.size() - 1));
 | 
			
		||||
 | 
			
		||||
        // add the output buses
 | 
			
		||||
        // This is incrdibly dumb: the output bus format must be well defined
 | 
			
		||||
        // This is incredibly dumb: the output bus format must be well defined
 | 
			
		||||
        // for every main bus in/out format pair. This means that there cannot
 | 
			
		||||
        // be two configurations with different aux formats but
 | 
			
		||||
        // identical main bus in/out formats.
 | 
			
		||||
 | 
			
		||||
@ -48,7 +48,7 @@
 | 
			
		||||
#include <CoreMIDI/CoreMIDI.h>
 | 
			
		||||
#include "CAXException.h"
 | 
			
		||||
 | 
			
		||||
//temporaray location
 | 
			
		||||
//temporary location
 | 
			
		||||
enum
 | 
			
		||||
{
 | 
			
		||||
	kMidiMessage_NoteOff 			= 0x80,
 | 
			
		||||
 | 
			
		||||
@ -130,7 +130,6 @@ public:
 | 
			
		||||
          MusicDeviceBase (component,
 | 
			
		||||
                           (UInt32) AudioUnitHelpers::getBusCount (juceFilter.get(), true),
 | 
			
		||||
                           (UInt32) AudioUnitHelpers::getBusCount (juceFilter.get(), false)),
 | 
			
		||||
          isBypassed (false),
 | 
			
		||||
          mapper (*juceFilter)
 | 
			
		||||
    {
 | 
			
		||||
        inParameterChangedCallback = false;
 | 
			
		||||
@ -474,6 +473,31 @@ public:
 | 
			
		||||
        {
 | 
			
		||||
            switch (inID)
 | 
			
		||||
            {
 | 
			
		||||
                case kAudioUnitProperty_ParameterClumpName:
 | 
			
		||||
 | 
			
		||||
                    if (auto* clumpNameInfo = (AudioUnitParameterNameInfo*) outData)
 | 
			
		||||
                    {
 | 
			
		||||
                        if (juceFilter != nullptr)
 | 
			
		||||
                        {
 | 
			
		||||
                            auto clumpIndex = clumpNameInfo->inID - 1;
 | 
			
		||||
                            const auto* group = parameterGroups[(int) clumpIndex];
 | 
			
		||||
                            auto name = group->getName();
 | 
			
		||||
 | 
			
		||||
                            while (group->getParent() != &juceFilter->getParameterTree())
 | 
			
		||||
                            {
 | 
			
		||||
                                group = group->getParent();
 | 
			
		||||
                                name = group->getName() + group->getSeparator() + name;
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
                            clumpNameInfo->outName = name.toCFString();
 | 
			
		||||
                            return noErr;
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    // Failed to find a group corresponding to the clump ID.
 | 
			
		||||
                    jassertfalse;
 | 
			
		||||
                    break;
 | 
			
		||||
 | 
			
		||||
                case juceFilterObjectPropertyID:
 | 
			
		||||
                    ((void**) outData)[0] = (void*) static_cast<AudioProcessor*> (juceFilter.get());
 | 
			
		||||
                    ((void**) outData)[1] = (void*) this;
 | 
			
		||||
@ -879,6 +903,14 @@ public:
 | 
			
		||||
                if (param->isMetaParameter())
 | 
			
		||||
                    outParameterInfo.flags |= kAudioUnitParameterFlag_IsGlobalMeta;
 | 
			
		||||
 | 
			
		||||
                auto parameterGroupHierarchy = juceFilter->getParameterTree().getGroupsForParameter (param);
 | 
			
		||||
 | 
			
		||||
                if (! parameterGroupHierarchy.isEmpty())
 | 
			
		||||
                {
 | 
			
		||||
                    outParameterInfo.flags |= kAudioUnitParameterFlag_HasClump;
 | 
			
		||||
                    outParameterInfo.clumpID = (UInt32) parameterGroups.indexOf (parameterGroupHierarchy.getLast()) + 1;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Is this a meter?
 | 
			
		||||
                if (((param->getCategory() & 0xffff0000) >> 16) == 2)
 | 
			
		||||
                {
 | 
			
		||||
@ -1429,7 +1461,6 @@ public:
 | 
			
		||||
    public:
 | 
			
		||||
        EditorCompHolder (AudioProcessorEditor* const editor)
 | 
			
		||||
        {
 | 
			
		||||
            setSize (editor->getWidth(), editor->getHeight());
 | 
			
		||||
            addAndMakeVisible (editor);
 | 
			
		||||
 | 
			
		||||
           #if ! JucePlugin_EditorRequiresKeyboardFocus
 | 
			
		||||
@ -1439,6 +1470,7 @@ public:
 | 
			
		||||
           #endif
 | 
			
		||||
 | 
			
		||||
            ignoreUnused (fakeMouseGenerator);
 | 
			
		||||
            setBounds (getSizeToContainChild());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ~EditorCompHolder()
 | 
			
		||||
@ -1447,13 +1479,21 @@ public:
 | 
			
		||||
                                 // have been transferred to another parent which takes over ownership.
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Rectangle<int> getSizeToContainChild()
 | 
			
		||||
        {
 | 
			
		||||
            if (auto* editor = getChildComponent (0))
 | 
			
		||||
                return getLocalArea (editor, editor->getLocalBounds());
 | 
			
		||||
 | 
			
		||||
            return {};
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        static NSView* createViewFor (AudioProcessor* filter, JuceAU* au, AudioProcessorEditor* const editor)
 | 
			
		||||
        {
 | 
			
		||||
            EditorCompHolder* editorCompHolder = new EditorCompHolder (editor);
 | 
			
		||||
            NSRect r = makeNSRect (editorCompHolder->getLocalBounds());
 | 
			
		||||
            auto* editorCompHolder = new EditorCompHolder (editor);
 | 
			
		||||
            auto r = makeNSRect (editorCompHolder->getSizeToContainChild());
 | 
			
		||||
 | 
			
		||||
            static JuceUIViewClass cls;
 | 
			
		||||
            NSView* view = [[cls.createInstance() initWithFrame: r] autorelease];
 | 
			
		||||
            auto* view = [[cls.createInstance() initWithFrame: r] autorelease];
 | 
			
		||||
 | 
			
		||||
            JuceUIViewClass::setFilter (view, filter);
 | 
			
		||||
            JuceUIViewClass::setAU (view, au);
 | 
			
		||||
@ -1470,29 +1510,33 @@ public:
 | 
			
		||||
 | 
			
		||||
            editorCompHolder->addToDesktop (0, (void*) view);
 | 
			
		||||
            editorCompHolder->setVisible (view);
 | 
			
		||||
 | 
			
		||||
            return view;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void childBoundsChanged (Component*) override
 | 
			
		||||
        {
 | 
			
		||||
            if (Component* editor = getChildComponent(0))
 | 
			
		||||
            auto b = getSizeToContainChild();
 | 
			
		||||
 | 
			
		||||
            if (lastBounds != b)
 | 
			
		||||
            {
 | 
			
		||||
                const int w = jmax (32, editor->getWidth());
 | 
			
		||||
                const int h = jmax (32, editor->getHeight());
 | 
			
		||||
                lastBounds = b;
 | 
			
		||||
 | 
			
		||||
                if (getWidth() != w || getHeight() != h)
 | 
			
		||||
                    setSize (w, h);
 | 
			
		||||
                auto w = jmax (32, b.getWidth());
 | 
			
		||||
                auto h = jmax (32, b.getHeight());
 | 
			
		||||
 | 
			
		||||
                NSView* view = (NSView*) getWindowHandle();
 | 
			
		||||
                NSRect r = [[view superview] frame];
 | 
			
		||||
                r.size.width = editor->getWidth();
 | 
			
		||||
                r.size.height = editor->getHeight();
 | 
			
		||||
                setSize (w, h);
 | 
			
		||||
 | 
			
		||||
                auto* view = (NSView*) getWindowHandle();
 | 
			
		||||
                auto r = [[view superview] frame];
 | 
			
		||||
                r.size.width  = w;
 | 
			
		||||
                r.size.height = h;
 | 
			
		||||
 | 
			
		||||
                [CATransaction begin];
 | 
			
		||||
                [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
 | 
			
		||||
                [CATransaction setValue:(id) kCFBooleanTrue forKey:kCATransactionDisableActions];
 | 
			
		||||
 | 
			
		||||
                [[view superview] setFrame: r];
 | 
			
		||||
                [view setFrame: makeNSRect (editor->getLocalBounds())];
 | 
			
		||||
                [view setFrame: makeNSRect (b)];
 | 
			
		||||
                [CATransaction commit];
 | 
			
		||||
 | 
			
		||||
                [view setNeedsDisplay: YES];
 | 
			
		||||
@ -1525,6 +1569,7 @@ public:
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
        FakeMouseMoveGenerator fakeMouseGenerator;
 | 
			
		||||
        Rectangle<int> lastBounds;
 | 
			
		||||
 | 
			
		||||
        JUCE_DECLARE_NON_COPYABLE (EditorCompHolder)
 | 
			
		||||
    };
 | 
			
		||||
@ -1674,7 +1719,7 @@ private:
 | 
			
		||||
    //==============================================================================
 | 
			
		||||
    AudioUnitHelpers::CoreAudioBufferList audioBuffer;
 | 
			
		||||
    MidiBuffer midiEvents, incomingEvents;
 | 
			
		||||
    bool prepared, isBypassed;
 | 
			
		||||
    bool prepared = false, isBypassed = false;
 | 
			
		||||
 | 
			
		||||
    //==============================================================================
 | 
			
		||||
   #if JUCE_FORCE_USE_LEGACY_PARAM_IDS
 | 
			
		||||
@ -1687,6 +1732,7 @@ private:
 | 
			
		||||
    LegacyAudioParametersWrapper juceParameters;
 | 
			
		||||
    HashMap<int32, AudioProcessorParameter*> paramMap;
 | 
			
		||||
    Array<AudioUnitParameterID> auParamIDs;
 | 
			
		||||
    Array<const AudioProcessorParameterGroup*> parameterGroups;
 | 
			
		||||
 | 
			
		||||
    //==============================================================================
 | 
			
		||||
    AudioUnitEvent auEvent;
 | 
			
		||||
@ -1839,6 +1885,8 @@ private:
 | 
			
		||||
    //==============================================================================
 | 
			
		||||
    void addParameters()
 | 
			
		||||
    {
 | 
			
		||||
        parameterGroups = juceFilter->getParameterTree().getSubgroups (true);
 | 
			
		||||
 | 
			
		||||
        juceParameters.update (*juceFilter, forceUseLegacyParamIDs);
 | 
			
		||||
        const int numParams = juceParameters.getNumParameters();
 | 
			
		||||
 | 
			
		||||
@ -1877,6 +1925,7 @@ private:
 | 
			
		||||
            OwnedArray<const __CFString>* stringValues = nullptr;
 | 
			
		||||
 | 
			
		||||
            auto initialValue = param->getValue();
 | 
			
		||||
            bool paramIsLegacy = dynamic_cast<LegacyAudioParameter*> (param) != nullptr;
 | 
			
		||||
 | 
			
		||||
            if (param->isDiscrete() && (! forceUseLegacyParamIDs))
 | 
			
		||||
            {
 | 
			
		||||
@ -1886,17 +1935,26 @@ private:
 | 
			
		||||
 | 
			
		||||
                const auto maxValue = getMaximumParameterValue (param);
 | 
			
		||||
 | 
			
		||||
                auto getTextValue = [param, paramIsLegacy] (float value)
 | 
			
		||||
                {
 | 
			
		||||
                    if (paramIsLegacy)
 | 
			
		||||
                    {
 | 
			
		||||
                        param->setValue (value);
 | 
			
		||||
                        return param->getCurrentValueAsText();
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    return param->getText (value, 256);
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
                for (int i = 0; i < numSteps; ++i)
 | 
			
		||||
                {
 | 
			
		||||
                    auto value = (float) i / maxValue;
 | 
			
		||||
 | 
			
		||||
                    // Once legacy parameters are deprecated this can be replaced by getText
 | 
			
		||||
                    param->setValue (value);
 | 
			
		||||
                    stringValues->add (CFStringCreateCopy (nullptr, (param->getCurrentValueAsText().toCFString())));
 | 
			
		||||
                    stringValues->add (CFStringCreateCopy (nullptr, (getTextValue (value).toCFString())));
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            param->setValue (initialValue);
 | 
			
		||||
            if (paramIsLegacy)
 | 
			
		||||
                param->setValue (initialValue);
 | 
			
		||||
 | 
			
		||||
            parameterValueStringArrays.add (stringValues);
 | 
			
		||||
        }
 | 
			
		||||
@ -1928,7 +1986,9 @@ private:
 | 
			
		||||
 | 
			
		||||
    AudioProcessorParameter* getParameterForAUParameterID (AudioUnitParameterID address) const noexcept
 | 
			
		||||
    {
 | 
			
		||||
        return paramMap[static_cast<int32> (address)];
 | 
			
		||||
        auto index = static_cast<int32> (address);
 | 
			
		||||
        return forceUseLegacyParamIDs ? juceParameters.getParamForIndex (index)
 | 
			
		||||
                                      : paramMap[index];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //==============================================================================
 | 
			
		||||
 | 
			
		||||
@ -847,6 +847,9 @@ public:
 | 
			
		||||
        processor.setRateAndBufferSizeDetails (sampleRate, static_cast<int> (maxFrames));
 | 
			
		||||
        processor.prepareToPlay (sampleRate, static_cast<int> (maxFrames));
 | 
			
		||||
 | 
			
		||||
        midiMessages.ensureSize (2048);
 | 
			
		||||
        midiMessages.clear();
 | 
			
		||||
 | 
			
		||||
        zeromem (&lastAudioHead, sizeof (lastAudioHead));
 | 
			
		||||
        hostMusicalContextCallback = [getAudioUnit() musicalContextBlock];
 | 
			
		||||
        hostTransportStateCallback = [getAudioUnit() transportStateBlock];
 | 
			
		||||
@ -887,7 +890,7 @@ public:
 | 
			
		||||
 | 
			
		||||
            for (auto i = 0u; i < n; ++i)
 | 
			
		||||
            {
 | 
			
		||||
                if (auto* viewConfiguration = [configs objectAtIndex:i])
 | 
			
		||||
                if (auto viewConfiguration = [configs objectAtIndex: i])
 | 
			
		||||
                {
 | 
			
		||||
                    if (editor->supportsHostMIDIControllerPresence ([viewConfiguration hostHasController] == YES))
 | 
			
		||||
                    {
 | 
			
		||||
@ -930,10 +933,12 @@ public:
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (isPositiveAndBelow (idx, juceParameters.getNumParameters()))
 | 
			
		||||
        if (auto* juceParam = juceParameters.getParamForIndex (idx))
 | 
			
		||||
        {
 | 
			
		||||
            if (AUParameter* param = [paramTree.get() parameterWithAddress: getAUParameterAddressForIndex (idx)])
 | 
			
		||||
            {
 | 
			
		||||
                newValue *= getMaximumParameterValue (juceParam);
 | 
			
		||||
 | 
			
		||||
                if (editorObserverToken != nullptr)
 | 
			
		||||
                    [param setValue: newValue  originator: editorObserverToken];
 | 
			
		||||
                else
 | 
			
		||||
@ -1152,107 +1157,175 @@ private:
 | 
			
		||||
       #endif
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::unique_ptr<AUParameter, NSObjectDeleter> createParameter (AudioProcessorParameter* parameter)
 | 
			
		||||
    {
 | 
			
		||||
        const String name (parameter->getName (512));
 | 
			
		||||
 | 
			
		||||
        AudioUnitParameterUnit unit = kAudioUnitParameterUnit_Generic;
 | 
			
		||||
        AudioUnitParameterOptions flags = (UInt32) (kAudioUnitParameterFlag_IsWritable
 | 
			
		||||
                                                  | kAudioUnitParameterFlag_IsReadable
 | 
			
		||||
                                                  | kAudioUnitParameterFlag_HasCFNameString
 | 
			
		||||
                                                  | kAudioUnitParameterFlag_ValuesHaveStrings);
 | 
			
		||||
 | 
			
		||||
        if (! forceLegacyParamIDs)
 | 
			
		||||
            flags |= (UInt32) kAudioUnitParameterFlag_IsHighResolution;
 | 
			
		||||
 | 
			
		||||
        // Set whether the param is automatable (unnamed parameters aren't allowed to be automated).
 | 
			
		||||
        if (name.isEmpty() || ! parameter->isAutomatable())
 | 
			
		||||
            flags |= kAudioUnitParameterFlag_NonRealTime;
 | 
			
		||||
 | 
			
		||||
        const bool isParameterDiscrete = parameter->isDiscrete();
 | 
			
		||||
 | 
			
		||||
        if (! isParameterDiscrete)
 | 
			
		||||
            flags |= kAudioUnitParameterFlag_CanRamp;
 | 
			
		||||
 | 
			
		||||
        if (parameter->isMetaParameter())
 | 
			
		||||
            flags |= kAudioUnitParameterFlag_IsGlobalMeta;
 | 
			
		||||
 | 
			
		||||
        std::unique_ptr<NSMutableArray, NSObjectDeleter> valueStrings;
 | 
			
		||||
 | 
			
		||||
        // Is this a meter?
 | 
			
		||||
        if (((parameter->getCategory() & 0xffff0000) >> 16) == 2)
 | 
			
		||||
        {
 | 
			
		||||
            flags &= ~kAudioUnitParameterFlag_IsWritable;
 | 
			
		||||
            flags |= kAudioUnitParameterFlag_MeterReadOnly | kAudioUnitParameterFlag_DisplayLogarithmic;
 | 
			
		||||
            unit = kAudioUnitParameterUnit_LinearGain;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            if (! forceLegacyParamIDs)
 | 
			
		||||
            {
 | 
			
		||||
                if (parameter->isDiscrete())
 | 
			
		||||
                {
 | 
			
		||||
                    unit = parameter->isBoolean() ? kAudioUnitParameterUnit_Boolean : kAudioUnitParameterUnit_Indexed;
 | 
			
		||||
                    auto maxValue = getMaximumParameterValue (parameter);
 | 
			
		||||
                    auto numSteps = parameter->getNumSteps();
 | 
			
		||||
 | 
			
		||||
                    // Some hosts can't handle the huge numbers of discrete parameter values created when
 | 
			
		||||
                    // using the default number of steps.
 | 
			
		||||
                    jassert (numSteps != AudioProcessor::getDefaultNumParameterSteps());
 | 
			
		||||
 | 
			
		||||
                    valueStrings.reset ([NSMutableArray new]);
 | 
			
		||||
 | 
			
		||||
                    for (int i = 0; i < numSteps; ++i)
 | 
			
		||||
                        [valueStrings.get() addObject: juceStringToNS (parameter->getText ((float) i / maxValue, 0))];
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        AUParameterAddress address = generateAUParameterAddress (parameter);
 | 
			
		||||
 | 
			
		||||
       #if ! JUCE_FORCE_USE_LEGACY_PARAM_IDS
 | 
			
		||||
        // If you hit this assertion then you have either put a parameter in two groups or you are
 | 
			
		||||
        // very unlucky and the hash codes of your parameter ids are not unique.
 | 
			
		||||
        jassert (! paramMap.contains (static_cast<int64> (address)));
 | 
			
		||||
 | 
			
		||||
        paramAddresses.add (address);
 | 
			
		||||
        paramMap.set (static_cast<int64> (address), parameter->getParameterIndex());
 | 
			
		||||
       #endif
 | 
			
		||||
 | 
			
		||||
        auto getParameterIdentifier = [parameter]
 | 
			
		||||
        {
 | 
			
		||||
            if (auto* paramWithID = dynamic_cast<AudioProcessorParameterWithID*> (parameter))
 | 
			
		||||
                return paramWithID->paramID;
 | 
			
		||||
 | 
			
		||||
            // This could clash if any groups have been given integer IDs!
 | 
			
		||||
            return String (parameter->getParameterIndex());
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        std::unique_ptr<AUParameter, NSObjectDeleter> param;
 | 
			
		||||
 | 
			
		||||
        @try
 | 
			
		||||
        {
 | 
			
		||||
            // Create methods in AUParameterTree return unretained objects (!) -> see Apple header AUAudioUnitImplementation.h
 | 
			
		||||
            param.reset([[AUParameterTree createParameterWithIdentifier: juceStringToNS (getParameterIdentifier())
 | 
			
		||||
                                                                   name: juceStringToNS (name)
 | 
			
		||||
                                                                address: address
 | 
			
		||||
                                                                    min: 0.0f
 | 
			
		||||
                                                                    max: getMaximumParameterValue (parameter)
 | 
			
		||||
                                                                   unit: unit
 | 
			
		||||
                                                               unitName: nullptr
 | 
			
		||||
                                                                  flags: flags
 | 
			
		||||
                                                           valueStrings: valueStrings.get()
 | 
			
		||||
                                                    dependentParameters: nullptr]
 | 
			
		||||
                         retain]);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @catch (NSException* exception)
 | 
			
		||||
        {
 | 
			
		||||
            // Do you have duplicate identifiers in any of your groups or parameters,
 | 
			
		||||
            // or do your identifiers have unusual characters in them?
 | 
			
		||||
            jassertfalse;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [param.get() setValue: parameter->getDefaultValue()];
 | 
			
		||||
 | 
			
		||||
        [overviewParams.get() addObject: [NSNumber numberWithUnsignedLongLong: address]];
 | 
			
		||||
 | 
			
		||||
        return param;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::unique_ptr<AUParameterGroup, NSObjectDeleter> createParameterGroup (AudioProcessorParameterGroup* group)
 | 
			
		||||
    {
 | 
			
		||||
        std::unique_ptr<NSMutableArray<AUParameterNode*>, NSObjectDeleter> children ([NSMutableArray<AUParameterNode*> new]);
 | 
			
		||||
 | 
			
		||||
        for (auto* node : *group)
 | 
			
		||||
        {
 | 
			
		||||
            if (auto* childGroup = node->getGroup())
 | 
			
		||||
                [children.get() addObject: createParameterGroup (childGroup).get()];
 | 
			
		||||
            else
 | 
			
		||||
                [children.get() addObject: createParameter (node->getParameter()).get()];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        std::unique_ptr<AUParameterGroup, NSObjectDeleter> result;
 | 
			
		||||
 | 
			
		||||
        @try
 | 
			
		||||
        {
 | 
			
		||||
            // Create methods in AUParameterTree return unretained objects (!) -> see Apple header AUAudioUnitImplementation.h
 | 
			
		||||
            result.reset ([[AUParameterTree createGroupWithIdentifier: juceStringToNS (group->getID())
 | 
			
		||||
                                                                 name: juceStringToNS (group->getName())
 | 
			
		||||
                                                             children: children.get()]
 | 
			
		||||
                           retain]);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @catch (NSException* exception)
 | 
			
		||||
        {
 | 
			
		||||
            // Do you have duplicate identifiers in any of your groups or parameters,
 | 
			
		||||
            // or do your identifiers have unusual characters in them?
 | 
			
		||||
            jassertfalse;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return result;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void addParameters()
 | 
			
		||||
    {
 | 
			
		||||
        std::unique_ptr<NSMutableArray<AUParameterNode*>, NSObjectDeleter> params ([[NSMutableArray<AUParameterNode*> alloc] init]);
 | 
			
		||||
 | 
			
		||||
        overviewParams.reset ([[NSMutableArray<NSNumber*> alloc] init]);
 | 
			
		||||
 | 
			
		||||
        auto& processor = getAudioProcessor();
 | 
			
		||||
        juceParameters.update (processor, forceLegacyParamIDs);
 | 
			
		||||
 | 
			
		||||
        const int n = juceParameters.getNumParameters();
 | 
			
		||||
        // This is updated when we build the tree.
 | 
			
		||||
        overviewParams.reset ([NSMutableArray<NSNumber*> new]);
 | 
			
		||||
 | 
			
		||||
        for (int idx = 0; idx < n; ++idx)
 | 
			
		||||
        {
 | 
			
		||||
            auto* juceParam = juceParameters.getParamForIndex (idx);
 | 
			
		||||
        std::unique_ptr<NSMutableArray<AUParameterNode*>, NSObjectDeleter> topLevelNodes ([NSMutableArray<AUParameterNode*> new]);
 | 
			
		||||
 | 
			
		||||
            const String identifier (idx);
 | 
			
		||||
            const String name = juceParam->getName (512);
 | 
			
		||||
 | 
			
		||||
            AudioUnitParameterUnit unit = kAudioUnitParameterUnit_Generic;
 | 
			
		||||
            AudioUnitParameterOptions flags = (UInt32) (kAudioUnitParameterFlag_IsWritable
 | 
			
		||||
                                                      | kAudioUnitParameterFlag_IsReadable
 | 
			
		||||
                                                      | kAudioUnitParameterFlag_HasCFNameString
 | 
			
		||||
                                                      | kAudioUnitParameterFlag_ValuesHaveStrings);
 | 
			
		||||
 | 
			
		||||
            if (! forceLegacyParamIDs)
 | 
			
		||||
                flags |= (UInt32) kAudioUnitParameterFlag_IsHighResolution;
 | 
			
		||||
 | 
			
		||||
            // set whether the param is automatable (unnamed parameters aren't allowed to be automated)
 | 
			
		||||
            if (name.isEmpty() || ! juceParam->isAutomatable())
 | 
			
		||||
                flags |= kAudioUnitParameterFlag_NonRealTime;
 | 
			
		||||
 | 
			
		||||
            const bool isParameterDiscrete = juceParam->isDiscrete();
 | 
			
		||||
 | 
			
		||||
            if (! isParameterDiscrete)
 | 
			
		||||
                flags |= kAudioUnitParameterFlag_CanRamp;
 | 
			
		||||
 | 
			
		||||
            if (juceParam->isMetaParameter())
 | 
			
		||||
                flags |= kAudioUnitParameterFlag_IsGlobalMeta;
 | 
			
		||||
 | 
			
		||||
            std::unique_ptr<NSMutableArray, NSObjectDeleter> valueStrings;
 | 
			
		||||
 | 
			
		||||
            // is this a meter?
 | 
			
		||||
            if (((juceParam->getCategory() & 0xffff0000) >> 16) == 2)
 | 
			
		||||
            {
 | 
			
		||||
                flags &= ~kAudioUnitParameterFlag_IsWritable;
 | 
			
		||||
                flags |= kAudioUnitParameterFlag_MeterReadOnly | kAudioUnitParameterFlag_DisplayLogarithmic;
 | 
			
		||||
                unit = kAudioUnitParameterUnit_LinearGain;
 | 
			
		||||
            }
 | 
			
		||||
        for (auto* node : processor.getParameterTree())
 | 
			
		||||
            if (auto* childGroup = node->getGroup())
 | 
			
		||||
                [topLevelNodes.get() addObject: createParameterGroup (childGroup).get()];
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                if (! forceLegacyParamIDs)
 | 
			
		||||
                {
 | 
			
		||||
                    if (juceParam->isDiscrete())
 | 
			
		||||
                    {
 | 
			
		||||
                        unit = juceParam->isBoolean() ? kAudioUnitParameterUnit_Boolean : kAudioUnitParameterUnit_Indexed;
 | 
			
		||||
                        auto maxValue = getMaximumParameterValue (juceParam);
 | 
			
		||||
                        auto numSteps = juceParam->getNumSteps();
 | 
			
		||||
                [topLevelNodes.get() addObject: createParameter (node->getParameter()).get()];
 | 
			
		||||
 | 
			
		||||
                        // Some hosts can't handle the huge numbers of discrete parameter values created when
 | 
			
		||||
                        // using the default number of steps.
 | 
			
		||||
                        jassert (numSteps != AudioProcessor::getDefaultNumParameterSteps());
 | 
			
		||||
 | 
			
		||||
                        valueStrings.reset ([NSMutableArray new]);
 | 
			
		||||
 | 
			
		||||
                        for (int i = 0; i < numSteps; ++i)
 | 
			
		||||
                            [valueStrings.get() addObject: juceStringToNS (juceParam->getText ((float) i / maxValue, 0))];
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            AUParameterAddress address = generateAUParameterAddress (juceParam);
 | 
			
		||||
 | 
			
		||||
           #if ! JUCE_FORCE_LEGACY_PARAMETER_AUTOMATION_TYPE
 | 
			
		||||
            // Consider yourself very unlucky if you hit this assertion. The hash codes of your
 | 
			
		||||
            // parameter ids are not unique.
 | 
			
		||||
            jassert (! paramMap.contains (static_cast<int64> (address)));
 | 
			
		||||
 | 
			
		||||
            paramAddresses.add (address);
 | 
			
		||||
            paramMap.set (static_cast<int64> (address), idx);
 | 
			
		||||
           #endif
 | 
			
		||||
 | 
			
		||||
            // create methods in AUParameterTree return unretained objects (!) -> see Apple header AUAudioUnitImplementation.h
 | 
			
		||||
            std::unique_ptr<AUParameter, NSObjectDeleter> param ([[AUParameterTree createParameterWithIdentifier: juceStringToNS (identifier)
 | 
			
		||||
                                                                                                            name: juceStringToNS (name)
 | 
			
		||||
                                                                                                         address: address
 | 
			
		||||
                                                                                                             min: 0.0f
 | 
			
		||||
                                                                                                             max: getMaximumParameterValue (juceParam)
 | 
			
		||||
                                                                                                            unit: unit
 | 
			
		||||
                                                                                                        unitName: nullptr
 | 
			
		||||
                                                                                                           flags: flags
 | 
			
		||||
                                                                                                    valueStrings: valueStrings.get()
 | 
			
		||||
                                                                                             dependentParameters: nullptr] retain]);
 | 
			
		||||
 | 
			
		||||
            [param.get() setValue: juceParam->getDefaultValue()];
 | 
			
		||||
 | 
			
		||||
            [params.get() addObject: param.get()];
 | 
			
		||||
            [overviewParams.get() addObject: [NSNumber numberWithUnsignedLongLong:address]];
 | 
			
		||||
        @try
 | 
			
		||||
        {
 | 
			
		||||
            // Create methods in AUParameterTree return unretained objects (!) -> see Apple header AUAudioUnitImplementation.h
 | 
			
		||||
            paramTree.reset ([[AUParameterTree createTreeWithChildren: topLevelNodes.get()] retain]);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // create methods in AUParameterTree return unretained objects (!) -> see Apple header AUAudioUnitImplementation.h
 | 
			
		||||
        paramTree.reset ([[AUParameterTree createTreeWithChildren: params.get()] retain]);
 | 
			
		||||
        @catch (NSException* exception)
 | 
			
		||||
        {
 | 
			
		||||
            // Do you have duplicate identifiers in any of your groups or parameters,
 | 
			
		||||
            // or do your identifiers have unusual characters in them?
 | 
			
		||||
            jassertfalse;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        paramObserver           = CreateObjCBlock (this, &JuceAudioUnitv3::valueChangedFromHost);
 | 
			
		||||
        paramProvider           = CreateObjCBlock (this, &JuceAudioUnitv3::getValue);
 | 
			
		||||
@ -1458,11 +1531,11 @@ private:
 | 
			
		||||
           #endif
 | 
			
		||||
 | 
			
		||||
            midiMessages.clear();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // copy back
 | 
			
		||||
        audioBuffer.pop (*outBusBuffers[(int) outputBusNumber]->get(),
 | 
			
		||||
                         mapper.get (false, (int) outputBusNumber));
 | 
			
		||||
            // copy back
 | 
			
		||||
            audioBuffer.pop (*outBusBuffers[(int) outputBusNumber]->get(),
 | 
			
		||||
                             mapper.get (false, (int) outputBusNumber));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return noErr;
 | 
			
		||||
    }
 | 
			
		||||
@ -1577,13 +1650,8 @@ private:
 | 
			
		||||
    {
 | 
			
		||||
        const String& juceParamID = LegacyAudioParameter::getParamID (param, forceLegacyParamIDs);
 | 
			
		||||
 | 
			
		||||
       #if JUCE_FORCE_USE_LEGACY_PARAM_IDS
 | 
			
		||||
        auto result = juceParamID.getIntValue();
 | 
			
		||||
       #else
 | 
			
		||||
        auto result = juceParamID.hashCode64();
 | 
			
		||||
       #endif
 | 
			
		||||
 | 
			
		||||
        return static_cast<AUParameterAddress> (result);
 | 
			
		||||
        return static_cast<AUParameterAddress> (forceLegacyParamIDs ? juceParamID.getIntValue()
 | 
			
		||||
                                                                    : juceParamID.hashCode64());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    AudioProcessorParameter* getJuceParameterForAUAddress (AUParameterAddress address) const noexcept
 | 
			
		||||
@ -1654,6 +1722,17 @@ JuceAudioUnitv3Base* JuceAudioUnitv3Base::create (AUAudioUnit* audioUnit, AudioC
 | 
			
		||||
    return new JuceAudioUnitv3 (audioUnit, descr, options, error);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if JUCE_IOS
 | 
			
		||||
namespace juce
 | 
			
		||||
{
 | 
			
		||||
struct UIViewPeerControllerReceiver
 | 
			
		||||
{
 | 
			
		||||
    virtual ~UIViewPeerControllerReceiver();
 | 
			
		||||
    virtual void setViewController (UIViewController*) = 0;
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//==============================================================================
 | 
			
		||||
class JuceAUViewController
 | 
			
		||||
{
 | 
			
		||||
@ -1661,15 +1740,13 @@ public:
 | 
			
		||||
    JuceAUViewController (AUViewController<AUAudioUnitFactory>* p)
 | 
			
		||||
        : myself (p)
 | 
			
		||||
    {
 | 
			
		||||
        jassert (MessageManager::getInstance()->isThisTheMessageThread());
 | 
			
		||||
 | 
			
		||||
        PluginHostType::jucePlugInClientCurrentWrapperType = AudioProcessor::wrapperType_AudioUnitv3;
 | 
			
		||||
        initialiseJuce_GUI();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ~JuceAUViewController()
 | 
			
		||||
    {
 | 
			
		||||
        jassert (MessageManager::getInstance()->isThisTheMessageThread());
 | 
			
		||||
        JUCE_ASSERT_MESSAGE_THREAD
 | 
			
		||||
 | 
			
		||||
        if (processorHolder != nullptr)
 | 
			
		||||
            JuceAudioUnitv3::removeEditor (getAudioProcessor());
 | 
			
		||||
@ -1678,7 +1755,7 @@ public:
 | 
			
		||||
    //==============================================================================
 | 
			
		||||
    void loadView()
 | 
			
		||||
    {
 | 
			
		||||
        jassert (MessageManager::getInstance()->isThisTheMessageThread());
 | 
			
		||||
        JUCE_ASSERT_MESSAGE_THREAD
 | 
			
		||||
 | 
			
		||||
        if (AudioProcessor* p = createPluginFilterOfType (AudioProcessor::wrapperType_AudioUnitv3))
 | 
			
		||||
        {
 | 
			
		||||
@ -1705,6 +1782,9 @@ public:
 | 
			
		||||
                   #if JUCE_IOS
 | 
			
		||||
                    if (JUCE_IOS_MAC_VIEW* peerView = [[[myself view] subviews] objectAtIndex: 0])
 | 
			
		||||
                        [peerView setContentMode: UIViewContentModeTop];
 | 
			
		||||
 | 
			
		||||
                    if (auto* peer = dynamic_cast<UIViewPeerControllerReceiver*> (editor->getPeer()))
 | 
			
		||||
                        peer->setViewController (myself);
 | 
			
		||||
                   #endif
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@ -1812,7 +1892,7 @@ private:
 | 
			
		||||
    //==============================================================================
 | 
			
		||||
    AUAudioUnit* createAudioUnitOnMessageThread (const AudioComponentDescription& descr, NSError** error)
 | 
			
		||||
    {
 | 
			
		||||
        jassert (MessageManager::getInstance()->isThisTheMessageThread());
 | 
			
		||||
        JUCE_ASSERT_MESSAGE_THREAD
 | 
			
		||||
 | 
			
		||||
        [myself view];  // this will call [view load] and ensure that the AudioProcessor has been instantiated
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -117,6 +117,9 @@ public:
 | 
			
		||||
    //==============================================================================
 | 
			
		||||
    void systemRequestedQuit() override
 | 
			
		||||
    {
 | 
			
		||||
        if (mainWindow.get() != nullptr)
 | 
			
		||||
            mainWindow->pluginHolder->savePluginState();
 | 
			
		||||
 | 
			
		||||
        if (ModalComponentManager::getInstance()->cancelAllModalComponents())
 | 
			
		||||
        {
 | 
			
		||||
            Timer::callAfterDelay (100, []()
 | 
			
		||||
 | 
			
		||||
@ -89,12 +89,14 @@ public:
 | 
			
		||||
        if (preferredSetupOptions != nullptr)
 | 
			
		||||
            options.reset (new AudioDeviceManager::AudioDeviceSetup (*preferredSetupOptions));
 | 
			
		||||
 | 
			
		||||
        if (inChannels > 0 && RuntimePermissions::isRequired (RuntimePermissions::recordAudio)
 | 
			
		||||
        auto audioInputRequired = (inChannels > 0);
 | 
			
		||||
 | 
			
		||||
        if (audioInputRequired && RuntimePermissions::isRequired (RuntimePermissions::recordAudio)
 | 
			
		||||
            && ! RuntimePermissions::isGranted (RuntimePermissions::recordAudio))
 | 
			
		||||
            RuntimePermissions::request (RuntimePermissions::recordAudio,
 | 
			
		||||
                                         [this, preferredDefaultDeviceName] (bool granted) { init (granted, preferredDefaultDeviceName); });
 | 
			
		||||
        else
 | 
			
		||||
            init (true, preferredDefaultDeviceName);
 | 
			
		||||
            init (audioInputRequired, preferredDefaultDeviceName);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void init (bool enableAudioInput, const String& preferredDefaultDeviceName)
 | 
			
		||||
@ -118,7 +120,6 @@ public:
 | 
			
		||||
    //==============================================================================
 | 
			
		||||
    virtual void createPlugin()
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
      #if JUCE_MODULE_AVAILABLE_juce_audio_plugin_client
 | 
			
		||||
        processor.reset (::createPluginFilterOfType (AudioProcessor::wrapperType_Standalone));
 | 
			
		||||
      #else
 | 
			
		||||
@ -427,7 +428,8 @@ private:
 | 
			
		||||
              deviceSelector (deviceManagerToUse,
 | 
			
		||||
                              minAudioInputChannels, maxAudioInputChannels,
 | 
			
		||||
                              minAudioOutputChannels, maxAudioOutputChannels,
 | 
			
		||||
                              true, false,
 | 
			
		||||
                              true,
 | 
			
		||||
                              (pluginHolder.processor.get() != nullptr && pluginHolder.processor->producesMidi()),
 | 
			
		||||
                              true, false),
 | 
			
		||||
              shouldMuteLabel  ("Feedback Loop:", "Feedback Loop:"),
 | 
			
		||||
              shouldMuteButton ("Mute audio input")
 | 
			
		||||
@ -508,10 +510,12 @@ private:
 | 
			
		||||
        emptyBuffer.clear();
 | 
			
		||||
 | 
			
		||||
        player.audioDeviceAboutToStart (device);
 | 
			
		||||
        player.setMidiOutput (deviceManager.getDefaultMidiOutput());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void audioDeviceStopped() override
 | 
			
		||||
    {
 | 
			
		||||
        player.setMidiOutput (nullptr);
 | 
			
		||||
        player.audioDeviceStopped();
 | 
			
		||||
        emptyBuffer.setSize (0, 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,191 @@
 | 
			
		||||
/*
 | 
			
		||||
  ==============================================================================
 | 
			
		||||
 | 
			
		||||
   This file is part of the JUCE library.
 | 
			
		||||
   Copyright (c) 2017 - ROLI Ltd.
 | 
			
		||||
 | 
			
		||||
   JUCE is an open source library subject to commercial or open-source
 | 
			
		||||
   licensing.
 | 
			
		||||
 | 
			
		||||
   By using JUCE, you agree to the terms of both the JUCE 5 End-User License
 | 
			
		||||
   Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
 | 
			
		||||
   27th April 2017).
 | 
			
		||||
 | 
			
		||||
   End User License Agreement: www.juce.com/juce-5-licence
 | 
			
		||||
   Privacy Policy: www.juce.com/juce-5-privacy-policy
 | 
			
		||||
 | 
			
		||||
   Or: You may also use this code under the terms of the GPL v3 (see
 | 
			
		||||
   www.gnu.org/licenses).
 | 
			
		||||
 | 
			
		||||
   JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
 | 
			
		||||
   EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
 | 
			
		||||
   DISCLAIMED.
 | 
			
		||||
 | 
			
		||||
  ==============================================================================
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//==============================================================================
 | 
			
		||||
#define UNITY_AUDIO_PLUGIN_API_VERSION 0x010401
 | 
			
		||||
 | 
			
		||||
#if JUCE_WINDOWS
 | 
			
		||||
 #define UNITY_INTERFACE_API __stdcall
 | 
			
		||||
 #define UNITY_INTERFACE_EXPORT __declspec(dllexport)
 | 
			
		||||
#else
 | 
			
		||||
 #define UNITY_INTERFACE_API
 | 
			
		||||
 #define UNITY_INTERFACE_EXPORT __attribute__ ((visibility("default")))
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//==============================================================================
 | 
			
		||||
struct UnityAudioEffectState;
 | 
			
		||||
 | 
			
		||||
typedef int  (UNITY_INTERFACE_API * createCallback)              (UnityAudioEffectState* state);
 | 
			
		||||
typedef int  (UNITY_INTERFACE_API * releaseCallback)             (UnityAudioEffectState* state);
 | 
			
		||||
typedef int  (UNITY_INTERFACE_API * resetCallback)               (UnityAudioEffectState* state);
 | 
			
		||||
 | 
			
		||||
typedef int  (UNITY_INTERFACE_API * processCallback)             (UnityAudioEffectState* state, float* inBuffer, float* outBuffer, unsigned int bufferSize,
 | 
			
		||||
                                                                  int numInChannels, int numOutChannels);
 | 
			
		||||
 | 
			
		||||
typedef int  (UNITY_INTERFACE_API * setPositionCallback)         (UnityAudioEffectState* state, unsigned int pos);
 | 
			
		||||
 | 
			
		||||
typedef int  (UNITY_INTERFACE_API * setFloatParameterCallback)   (UnityAudioEffectState* state, int index, float value);
 | 
			
		||||
typedef int  (UNITY_INTERFACE_API * getFloatParameterCallback)   (UnityAudioEffectState* state, int index, float* value, char* valuestr);
 | 
			
		||||
typedef int  (UNITY_INTERFACE_API * getFloatBufferCallback)      (UnityAudioEffectState* state, const char* name, float* buffer, int numsamples);
 | 
			
		||||
 | 
			
		||||
typedef int  (UNITY_INTERFACE_API * distanceAttenuationCallback) (UnityAudioEffectState* state, float distanceIn, float attenuationIn, float* attenuationOut);
 | 
			
		||||
 | 
			
		||||
typedef void (UNITY_INTERFACE_API * renderCallback)              (int eventId);
 | 
			
		||||
 | 
			
		||||
//==============================================================================
 | 
			
		||||
enum UnityAudioEffectDefinitionFlags
 | 
			
		||||
{
 | 
			
		||||
    isSideChainTarget = 1,
 | 
			
		||||
    isSpatializer = 2,
 | 
			
		||||
    isAmbisonicDecoder = 4,
 | 
			
		||||
    appliesDistanceAttenuation = 8
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum UnityAudioEffectStateFlags
 | 
			
		||||
{
 | 
			
		||||
    stateIsPlaying = 1,
 | 
			
		||||
    stateIsPaused = 2,
 | 
			
		||||
    stateIsMuted = 8,
 | 
			
		||||
    statIsSideChainTarget = 16
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum UnityEventModifiers
 | 
			
		||||
{
 | 
			
		||||
    shift = 1,
 | 
			
		||||
    control = 2,
 | 
			
		||||
    alt = 4,
 | 
			
		||||
    command = 8,
 | 
			
		||||
    numeric = 16,
 | 
			
		||||
    capsLock = 32,
 | 
			
		||||
    functionKey = 64
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//==============================================================================
 | 
			
		||||
struct UnityAudioSpatializerData
 | 
			
		||||
{
 | 
			
		||||
    float                          listenerMatrix[16];
 | 
			
		||||
    float                          sourceMatrix[16];
 | 
			
		||||
    float                          spatialBlend;
 | 
			
		||||
    float                          reverbZoneMix;
 | 
			
		||||
    float                          spread;
 | 
			
		||||
    float                          stereoPan;
 | 
			
		||||
    distanceAttenuationCallback    attenuationCallback;
 | 
			
		||||
    float                          minDistance;
 | 
			
		||||
    float                          maxDistance;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct UnityAudioAmbisonicData
 | 
			
		||||
{
 | 
			
		||||
    float                          listenerMatrix[16];
 | 
			
		||||
    float                          sourceMatrix[16];
 | 
			
		||||
    float                          spatialBlend;
 | 
			
		||||
    float                          reverbZoneMix;
 | 
			
		||||
    float                          spread;
 | 
			
		||||
    float                          stereoPan;
 | 
			
		||||
    distanceAttenuationCallback    attenuationCallback;
 | 
			
		||||
    int                            ambisonicOutChannels;
 | 
			
		||||
    float                          volume;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct UnityAudioEffectState
 | 
			
		||||
{
 | 
			
		||||
    juce::uint32               structSize;
 | 
			
		||||
    juce::uint32               sampleRate;
 | 
			
		||||
    juce::uint64               dspCurrentTick;
 | 
			
		||||
    juce::uint64               dspPreviousTick;
 | 
			
		||||
    float*                     sidechainBuffer;
 | 
			
		||||
    void*                      effectData;
 | 
			
		||||
    juce::uint32               flags;
 | 
			
		||||
    void*                      internal;
 | 
			
		||||
 | 
			
		||||
    UnityAudioSpatializerData* spatializerData;
 | 
			
		||||
    juce::uint32               dspBufferSize;
 | 
			
		||||
    juce::uint32               hostAPIVersion;
 | 
			
		||||
 | 
			
		||||
    UnityAudioAmbisonicData*   ambisonicData;
 | 
			
		||||
 | 
			
		||||
    template<typename T>
 | 
			
		||||
    inline T* getEffectData() const
 | 
			
		||||
    {
 | 
			
		||||
        jassert (effectData != nullptr);
 | 
			
		||||
        jassert (internal != nullptr);
 | 
			
		||||
 | 
			
		||||
        return (T*) effectData;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct UnityAudioParameterDefinition
 | 
			
		||||
{
 | 
			
		||||
    char        name[16];
 | 
			
		||||
    char        unit[16];
 | 
			
		||||
    const char* description;
 | 
			
		||||
    float       min;
 | 
			
		||||
    float       max;
 | 
			
		||||
    float       defaultVal;
 | 
			
		||||
    float       displayScale;
 | 
			
		||||
    float       displayExponent;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct UnityAudioEffectDefinition
 | 
			
		||||
{
 | 
			
		||||
    juce::uint32                   structSize;
 | 
			
		||||
    juce::uint32                   parameterStructSize;
 | 
			
		||||
    juce::uint32                   apiVersion;
 | 
			
		||||
    juce::uint32                   pluginVersion;
 | 
			
		||||
    juce::uint32                   channels;
 | 
			
		||||
    juce::uint32                   numParameters;
 | 
			
		||||
    juce::uint64                   flags;
 | 
			
		||||
    char                           name[32];
 | 
			
		||||
    createCallback                 create;
 | 
			
		||||
    releaseCallback                release;
 | 
			
		||||
    resetCallback                  reset;
 | 
			
		||||
    processCallback                process;
 | 
			
		||||
    setPositionCallback            setPosition;
 | 
			
		||||
    UnityAudioParameterDefinition* parameterDefintions;
 | 
			
		||||
    setFloatParameterCallback      setFloatParameter;
 | 
			
		||||
    getFloatParameterCallback      getFloatParameter;
 | 
			
		||||
    getFloatBufferCallback         getFloatBuffer;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//==============================================================================
 | 
			
		||||
// Unity callback
 | 
			
		||||
extern "C" UNITY_INTERFACE_EXPORT int  UNITY_INTERFACE_API UnityGetAudioEffectDefinitions (UnityAudioEffectDefinition*** definitionsPtr);
 | 
			
		||||
 | 
			
		||||
// GUI script callbacks
 | 
			
		||||
extern "C" UNITY_INTERFACE_EXPORT renderCallback UNITY_INTERFACE_API getRenderCallback();
 | 
			
		||||
 | 
			
		||||
extern "C" UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API unityInitialiseTexture (int id, void* textureHandle, int w, int h);
 | 
			
		||||
 | 
			
		||||
extern "C" UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API unityMouseDown (int id, float x, float y, UnityEventModifiers mods, int button);
 | 
			
		||||
extern "C" UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API unityMouseDrag (int id, float x, float y, UnityEventModifiers mods, int button);
 | 
			
		||||
extern "C" UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API unityMouseUp   (int id, float x, float y, UnityEventModifiers mods);
 | 
			
		||||
 | 
			
		||||
extern "C" UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API unityKeyEvent (int id, int code, UnityEventModifiers mods, const char* name);
 | 
			
		||||
 | 
			
		||||
extern "C" UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API unitySetScreenBounds (int id, float x, float y, float w, float h);
 | 
			
		||||
							
								
								
									
										768
									
								
								modules/juce_audio_plugin_client/Unity/juce_Unity_Wrapper.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										768
									
								
								modules/juce_audio_plugin_client/Unity/juce_Unity_Wrapper.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,768 @@
 | 
			
		||||
/*
 | 
			
		||||
  ==============================================================================
 | 
			
		||||
 | 
			
		||||
   This file is part of the JUCE library.
 | 
			
		||||
   Copyright (c) 2017 - ROLI Ltd.
 | 
			
		||||
 | 
			
		||||
   JUCE is an open source library subject to commercial or open-source
 | 
			
		||||
   licensing.
 | 
			
		||||
 | 
			
		||||
   By using JUCE, you agree to the terms of both the JUCE 5 End-User License
 | 
			
		||||
   Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
 | 
			
		||||
   27th April 2017).
 | 
			
		||||
 | 
			
		||||
   End User License Agreement: www.juce.com/juce-5-licence
 | 
			
		||||
   Privacy Policy: www.juce.com/juce-5-privacy-policy
 | 
			
		||||
 | 
			
		||||
   Or: You may also use this code under the terms of the GPL v3 (see
 | 
			
		||||
   www.gnu.org/licenses).
 | 
			
		||||
 | 
			
		||||
   JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
 | 
			
		||||
   EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
 | 
			
		||||
   DISCLAIMED.
 | 
			
		||||
 | 
			
		||||
  ==============================================================================
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#if JucePlugin_Build_Unity
 | 
			
		||||
 | 
			
		||||
#include "../../juce_core/system/juce_TargetPlatform.h"
 | 
			
		||||
#include "../utility/juce_IncludeModuleHeaders.h"
 | 
			
		||||
#include "../../juce_audio_processors/format_types/juce_LegacyAudioParameter.cpp"
 | 
			
		||||
 | 
			
		||||
#if JUCE_WINDOWS
 | 
			
		||||
 #include "../utility/juce_IncludeSystemHeaders.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "juce_UnityPluginInterface.h"
 | 
			
		||||
 | 
			
		||||
//==============================================================================
 | 
			
		||||
namespace juce
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
typedef ComponentPeer* (*createUnityPeerFunctionType) (Component&);
 | 
			
		||||
extern createUnityPeerFunctionType juce_createUnityPeerFn;
 | 
			
		||||
 | 
			
		||||
//==============================================================================
 | 
			
		||||
class UnityPeer    : public ComponentPeer,
 | 
			
		||||
                     public AsyncUpdater
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    UnityPeer (Component& ed)
 | 
			
		||||
        : ComponentPeer (ed, 0),
 | 
			
		||||
          mouseWatcher (*this)
 | 
			
		||||
    {
 | 
			
		||||
        getEditor().setResizable (false, false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //==============================================================================
 | 
			
		||||
    Rectangle<int> getBounds() const override                              { return bounds; }
 | 
			
		||||
    Point<float> localToGlobal (Point<float> relativePosition) override    { return relativePosition + getBounds().getPosition().toFloat(); }
 | 
			
		||||
    Point<float> globalToLocal (Point<float> screenPosition) override      { return screenPosition - getBounds().getPosition().toFloat(); }
 | 
			
		||||
 | 
			
		||||
    StringArray getAvailableRenderingEngines() override                    { return StringArray ("Software Renderer"); }
 | 
			
		||||
 | 
			
		||||
    void setBounds (const Rectangle<int>& newBounds, bool) override
 | 
			
		||||
    {
 | 
			
		||||
        bounds = newBounds;
 | 
			
		||||
        mouseWatcher.setBoundsToWatch (bounds);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool contains (Point<int> localPos, bool) const override
 | 
			
		||||
    {
 | 
			
		||||
        if (isPositiveAndBelow (localPos.getX(), getBounds().getWidth())
 | 
			
		||||
               && isPositiveAndBelow (localPos.getY(), getBounds().getHeight()))
 | 
			
		||||
            return true;
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void handleAsyncUpdate() override
 | 
			
		||||
    {
 | 
			
		||||
        fillPixels();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //==============================================================================
 | 
			
		||||
    AudioProcessorEditor& getEditor()    { return *dynamic_cast<AudioProcessorEditor*> (&getComponent()); }
 | 
			
		||||
 | 
			
		||||
    void setPixelDataHandle (uint8* handle, int width, int height)
 | 
			
		||||
    {
 | 
			
		||||
        pixelData = handle;
 | 
			
		||||
 | 
			
		||||
        textureWidth = width;
 | 
			
		||||
        textureHeight = height;
 | 
			
		||||
 | 
			
		||||
        renderImage = Image (new UnityBitmapImage (pixelData, width, height));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // N.B. This is NOT an efficient way to do this and you shouldn't use this method in your own code.
 | 
			
		||||
    // It works for our purposes here but a much more efficient way would be to use a GL texture.
 | 
			
		||||
    void fillPixels()
 | 
			
		||||
    {
 | 
			
		||||
        if (pixelData == nullptr)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        LowLevelGraphicsSoftwareRenderer renderer (renderImage);
 | 
			
		||||
        renderer.addTransform (AffineTransform::verticalFlip ((float) getComponent().getHeight()));
 | 
			
		||||
 | 
			
		||||
        handlePaint (renderer);
 | 
			
		||||
 | 
			
		||||
        for (int i = 0; i < textureWidth * textureHeight * 4; i += 4)
 | 
			
		||||
        {
 | 
			
		||||
            auto r = pixelData[i + 2];
 | 
			
		||||
            auto g = pixelData[i + 1];
 | 
			
		||||
            auto b = pixelData[i + 0];
 | 
			
		||||
 | 
			
		||||
            pixelData[i + 0] = r;
 | 
			
		||||
            pixelData[i + 1] = g;
 | 
			
		||||
            pixelData[i + 2] = b;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void forwardMouseEvent (Point<float> position, ModifierKeys mods)
 | 
			
		||||
    {
 | 
			
		||||
        ModifierKeys::currentModifiers = mods;
 | 
			
		||||
 | 
			
		||||
        handleMouseEvent (juce::MouseInputSource::mouse, position, mods, juce::MouseInputSource::invalidPressure,
 | 
			
		||||
                          juce::MouseInputSource::invalidOrientation, juce::Time::currentTimeMillis());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void forwardKeyPress (int code, String name, ModifierKeys mods)
 | 
			
		||||
    {
 | 
			
		||||
        ModifierKeys::currentModifiers = mods;
 | 
			
		||||
 | 
			
		||||
        handleKeyPress (getKeyPress (code, name));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    //==============================================================================
 | 
			
		||||
    struct UnityBitmapImage    : public ImagePixelData
 | 
			
		||||
    {
 | 
			
		||||
        UnityBitmapImage (uint8* data, int w, int h)
 | 
			
		||||
            : ImagePixelData (Image::PixelFormat::ARGB, w, h),
 | 
			
		||||
              imageData (data),
 | 
			
		||||
              lineStride (width * pixelStride)
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ImageType* createType() const override                       { return new SoftwareImageType(); }
 | 
			
		||||
        LowLevelGraphicsContext* createLowLevelContext() override    { return new LowLevelGraphicsSoftwareRenderer (Image (this)); }
 | 
			
		||||
 | 
			
		||||
        void initialiseBitmapData (Image::BitmapData& bitmap, int x, int y, Image::BitmapData::ReadWriteMode mode) override
 | 
			
		||||
        {
 | 
			
		||||
            ignoreUnused (mode);
 | 
			
		||||
 | 
			
		||||
            bitmap.data = imageData + x * pixelStride + y * lineStride;
 | 
			
		||||
            bitmap.pixelFormat = pixelFormat;
 | 
			
		||||
            bitmap.lineStride = lineStride;
 | 
			
		||||
            bitmap.pixelStride = pixelStride;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ImagePixelData::Ptr clone() override
 | 
			
		||||
        {
 | 
			
		||||
            auto im = new UnityBitmapImage (imageData, width, height);
 | 
			
		||||
 | 
			
		||||
            for (int i = 0; i < height; ++i)
 | 
			
		||||
                memcpy (im->imageData + i * lineStride, imageData + i * lineStride, (size_t) lineStride);
 | 
			
		||||
 | 
			
		||||
            return im;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        uint8* imageData;
 | 
			
		||||
        int pixelStride = 4, lineStride;
 | 
			
		||||
 | 
			
		||||
        JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (UnityBitmapImage)
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    //==============================================================================
 | 
			
		||||
    struct MouseWatcher    : public Timer
 | 
			
		||||
    {
 | 
			
		||||
        MouseWatcher (ComponentPeer& o)    : owner (o)    {}
 | 
			
		||||
 | 
			
		||||
        void timerCallback() override
 | 
			
		||||
        {
 | 
			
		||||
            auto pos = Desktop::getMousePosition();
 | 
			
		||||
 | 
			
		||||
            if (boundsToWatch.contains (pos) && pos != lastMousePos)
 | 
			
		||||
            {
 | 
			
		||||
                auto ms = Desktop::getInstance().getMainMouseSource();
 | 
			
		||||
 | 
			
		||||
                if (! ms.getCurrentModifiers().isLeftButtonDown())
 | 
			
		||||
                    owner.handleMouseEvent (juce::MouseInputSource::mouse, owner.globalToLocal (pos.toFloat()), {},
 | 
			
		||||
                                            juce::MouseInputSource::invalidPressure, juce::MouseInputSource::invalidOrientation, juce::Time::currentTimeMillis());
 | 
			
		||||
 | 
			
		||||
                lastMousePos = pos;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void setBoundsToWatch (Rectangle<int> b)
 | 
			
		||||
        {
 | 
			
		||||
            if (boundsToWatch != b)
 | 
			
		||||
                boundsToWatch = b;
 | 
			
		||||
 | 
			
		||||
            startTimer (250);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ComponentPeer& owner;
 | 
			
		||||
        Rectangle<int> boundsToWatch;
 | 
			
		||||
        Point<int> lastMousePos;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    //==============================================================================
 | 
			
		||||
    KeyPress getKeyPress (int keyCode, String name)
 | 
			
		||||
    {
 | 
			
		||||
        if (keyCode >= 32 && keyCode <= 64)
 | 
			
		||||
            return { keyCode, ModifierKeys::currentModifiers, juce::juce_wchar (keyCode) };
 | 
			
		||||
 | 
			
		||||
        if (keyCode >= 91 && keyCode <= 122)
 | 
			
		||||
            return { keyCode, ModifierKeys::currentModifiers, name[0] };
 | 
			
		||||
 | 
			
		||||
        if (keyCode >= 256 && keyCode <= 265)
 | 
			
		||||
            return { juce::KeyPress::numberPad0 + (keyCode - 256), ModifierKeys::currentModifiers, juce::String (keyCode - 256).getCharPointer()[0] };
 | 
			
		||||
 | 
			
		||||
        if (keyCode == 8)      return { juce::KeyPress::backspaceKey,          ModifierKeys::currentModifiers, {} };
 | 
			
		||||
        if (keyCode == 127)    return { juce::KeyPress::deleteKey,             ModifierKeys::currentModifiers, {} };
 | 
			
		||||
        if (keyCode == 9)      return { juce::KeyPress::tabKey,                ModifierKeys::currentModifiers, {} };
 | 
			
		||||
        if (keyCode == 13)     return { juce::KeyPress::returnKey,             ModifierKeys::currentModifiers, {} };
 | 
			
		||||
        if (keyCode == 27)     return { juce::KeyPress::escapeKey,             ModifierKeys::currentModifiers, {} };
 | 
			
		||||
        if (keyCode == 32)     return { juce::KeyPress::spaceKey,              ModifierKeys::currentModifiers, {} };
 | 
			
		||||
        if (keyCode == 266)    return { juce::KeyPress::numberPadDecimalPoint, ModifierKeys::currentModifiers, {} };
 | 
			
		||||
        if (keyCode == 267)    return { juce::KeyPress::numberPadDivide,       ModifierKeys::currentModifiers, {} };
 | 
			
		||||
        if (keyCode == 268)    return { juce::KeyPress::numberPadMultiply,     ModifierKeys::currentModifiers, {} };
 | 
			
		||||
        if (keyCode == 269)    return { juce::KeyPress::numberPadSubtract,     ModifierKeys::currentModifiers, {} };
 | 
			
		||||
        if (keyCode == 270)    return { juce::KeyPress::numberPadAdd,          ModifierKeys::currentModifiers, {} };
 | 
			
		||||
        if (keyCode == 272)    return { juce::KeyPress::numberPadEquals,       ModifierKeys::currentModifiers, {} };
 | 
			
		||||
        if (keyCode == 273)    return { juce::KeyPress::upKey,                 ModifierKeys::currentModifiers, {} };
 | 
			
		||||
        if (keyCode == 274)    return { juce::KeyPress::downKey,               ModifierKeys::currentModifiers, {} };
 | 
			
		||||
        if (keyCode == 275)    return { juce::KeyPress::rightKey,              ModifierKeys::currentModifiers, {} };
 | 
			
		||||
        if (keyCode == 276)    return { juce::KeyPress::leftKey,               ModifierKeys::currentModifiers, {} };
 | 
			
		||||
 | 
			
		||||
        return {};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //==============================================================================
 | 
			
		||||
    Rectangle<int> bounds;
 | 
			
		||||
    MouseWatcher mouseWatcher;
 | 
			
		||||
 | 
			
		||||
    uint8* pixelData = nullptr;
 | 
			
		||||
    int textureWidth, textureHeight;
 | 
			
		||||
    Image renderImage;
 | 
			
		||||
 | 
			
		||||
    //==============================================================================
 | 
			
		||||
    void setMinimised (bool) override                                 {}
 | 
			
		||||
    bool isMinimised() const override                                 { return false; }
 | 
			
		||||
    void setFullScreen (bool) override                                {}
 | 
			
		||||
    bool isFullScreen() const override                                { return false; }
 | 
			
		||||
    bool setAlwaysOnTop (bool) override                               { return false; }
 | 
			
		||||
    void toFront (bool) override                                      {}
 | 
			
		||||
    void toBehind (ComponentPeer*) override                           {}
 | 
			
		||||
    bool isFocused() const override                                   { return true; }
 | 
			
		||||
    void grabFocus() override                                         {}
 | 
			
		||||
    void* getNativeHandle() const override                            { return nullptr; }
 | 
			
		||||
    BorderSize<int> getFrameSize() const override                     { return {}; }
 | 
			
		||||
    void setVisible (bool) override                                   {}
 | 
			
		||||
    void setTitle (const String&) override                            {}
 | 
			
		||||
    void setIcon (const Image&) override                              {}
 | 
			
		||||
    void textInputRequired (Point<int>, TextInputTarget&) override    {}
 | 
			
		||||
    void setAlpha (float) override                                    {}
 | 
			
		||||
    void performAnyPendingRepaintsNow() override                      {}
 | 
			
		||||
    void repaint (const Rectangle<int>&) override                     {}
 | 
			
		||||
 | 
			
		||||
    //==============================================================================
 | 
			
		||||
    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (UnityPeer)
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
ComponentPeer* createUnityPeer (Component& c)    { return new UnityPeer (c); }
 | 
			
		||||
 | 
			
		||||
//==============================================================================
 | 
			
		||||
class AudioProcessorUnityWrapper
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    AudioProcessorUnityWrapper (bool isTemporary)
 | 
			
		||||
    {
 | 
			
		||||
        pluginInstance.reset (createPluginFilterOfType (AudioProcessor::wrapperType_Unity));
 | 
			
		||||
 | 
			
		||||
        if (! isTemporary && pluginInstance->hasEditor())
 | 
			
		||||
        {
 | 
			
		||||
            pluginInstanceEditor.reset (pluginInstance->createEditorIfNeeded());
 | 
			
		||||
            pluginInstanceEditor->setVisible (true);
 | 
			
		||||
            pluginInstanceEditor->addToDesktop (0);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        juceParameters.update (*pluginInstance, false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ~AudioProcessorUnityWrapper()
 | 
			
		||||
    {
 | 
			
		||||
        if (pluginInstanceEditor != nullptr)
 | 
			
		||||
        {
 | 
			
		||||
            pluginInstanceEditor->removeFromDesktop();
 | 
			
		||||
 | 
			
		||||
            PopupMenu::dismissAllActiveMenus();
 | 
			
		||||
            pluginInstanceEditor->processor.editorBeingDeleted (pluginInstanceEditor.get());
 | 
			
		||||
            pluginInstanceEditor = nullptr;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void create (UnityAudioEffectState* state)
 | 
			
		||||
    {
 | 
			
		||||
        // only supported in Unity plugin API > 1.0
 | 
			
		||||
        if (state->structSize >= sizeof (UnityAudioEffectState))
 | 
			
		||||
            samplesPerBlock = static_cast<int> (state->dspBufferSize);
 | 
			
		||||
 | 
			
		||||
       #ifdef JucePlugin_PreferredChannelConfigurations
 | 
			
		||||
        short configs[][2] = { JucePlugin_PreferredChannelConfigurations };
 | 
			
		||||
        const int numConfigs = sizeof (configs) / sizeof (short[2]);
 | 
			
		||||
 | 
			
		||||
        jassert (numConfigs > 0 && (configs[0][0] > 0 || configs[0][1] > 0));
 | 
			
		||||
 | 
			
		||||
        pluginInstance->setPlayConfigDetails (configs[0][0], configs[0][1], state->sampleRate, samplesPerBlock);
 | 
			
		||||
       #else
 | 
			
		||||
        pluginInstance->setRateAndBufferSizeDetails (state->sampleRate, samplesPerBlock);
 | 
			
		||||
       #endif
 | 
			
		||||
 | 
			
		||||
        pluginInstance->prepareToPlay (state->sampleRate, samplesPerBlock);
 | 
			
		||||
 | 
			
		||||
        scratchBuffer.setSize (jmax (pluginInstance->getTotalNumInputChannels(), pluginInstance->getTotalNumOutputChannels()), samplesPerBlock);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void release()
 | 
			
		||||
    {
 | 
			
		||||
        pluginInstance->releaseResources();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void reset()
 | 
			
		||||
    {
 | 
			
		||||
        pluginInstance->reset();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void process (float* inBuffer, float* outBuffer, int bufferSize, int numInChannels, int numOutChannels, bool isBypassed)
 | 
			
		||||
    {
 | 
			
		||||
        for (int pos = 0; pos < bufferSize;)
 | 
			
		||||
        {
 | 
			
		||||
            auto max = jmin (bufferSize - pos, samplesPerBlock);
 | 
			
		||||
            processBuffers (inBuffer + (pos * numInChannels), outBuffer + (pos * numOutChannels), max, numInChannels, numOutChannels, isBypassed);
 | 
			
		||||
 | 
			
		||||
            pos += max;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declareParameters (UnityAudioEffectDefinition& definition)
 | 
			
		||||
    {
 | 
			
		||||
        static std::unique_ptr<UnityAudioParameterDefinition> parametersPtr;
 | 
			
		||||
        static int numParams = 0;
 | 
			
		||||
 | 
			
		||||
        if (parametersPtr == nullptr)
 | 
			
		||||
        {
 | 
			
		||||
            numParams = juceParameters.params.size();
 | 
			
		||||
 | 
			
		||||
            parametersPtr.reset (static_cast<UnityAudioParameterDefinition*> (std::calloc (static_cast<size_t> (numParams),
 | 
			
		||||
                                                                              sizeof (UnityAudioParameterDefinition))));
 | 
			
		||||
 | 
			
		||||
            parameterDescriptions.clear();
 | 
			
		||||
 | 
			
		||||
            for (int i = 0; i < numParams; ++i)
 | 
			
		||||
            {
 | 
			
		||||
                auto* parameter = juceParameters.params[i];
 | 
			
		||||
                auto& paramDef = parametersPtr.get()[i];
 | 
			
		||||
 | 
			
		||||
                strncpy (paramDef.name, parameter->getName (15).toRawUTF8(), 15);
 | 
			
		||||
 | 
			
		||||
                if (parameter->getLabel().isNotEmpty())
 | 
			
		||||
                    strncpy (paramDef.unit, parameter->getLabel().toRawUTF8(), 15);
 | 
			
		||||
 | 
			
		||||
                parameterDescriptions.add (parameter->getName (15));
 | 
			
		||||
                paramDef.description = parameterDescriptions[i].toRawUTF8();
 | 
			
		||||
 | 
			
		||||
                paramDef.defaultVal = parameter->getDefaultValue();
 | 
			
		||||
                paramDef.min = 0.0f;
 | 
			
		||||
                paramDef.max = 1.0f;
 | 
			
		||||
                paramDef.displayScale = 1.0f;
 | 
			
		||||
                paramDef.displayExponent = 1.0f;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        definition.numParameters = static_cast<uint32> (numParams);
 | 
			
		||||
        definition.parameterDefintions = parametersPtr.get();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void setParameter (int index, float value)       { juceParameters.getParamForIndex (index)->setValueNotifyingHost (value); }
 | 
			
		||||
    float getParameter (int index) const noexcept    { return juceParameters.getParamForIndex (index)->getValue(); }
 | 
			
		||||
 | 
			
		||||
    String getParameterString (int index) const noexcept
 | 
			
		||||
    {
 | 
			
		||||
        auto* param = juceParameters.getParamForIndex (index);
 | 
			
		||||
        return param->getText (param->getValue(), 16);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int getNumInputChannels() const noexcept         { return pluginInstance->getTotalNumInputChannels(); }
 | 
			
		||||
    int getNumOutputChannels() const noexcept        { return pluginInstance->getTotalNumOutputChannels(); }
 | 
			
		||||
 | 
			
		||||
    bool hasEditor() const noexcept                  { return pluginInstance->hasEditor(); }
 | 
			
		||||
 | 
			
		||||
    UnityPeer& getEditorPeer() const
 | 
			
		||||
    {
 | 
			
		||||
        auto* peer = dynamic_cast<UnityPeer*> (pluginInstanceEditor->getPeer());
 | 
			
		||||
 | 
			
		||||
        jassert (peer != nullptr);
 | 
			
		||||
        return *peer;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    //==============================================================================
 | 
			
		||||
    void processBuffers (float* inBuffer, float* outBuffer, int bufferSize, int numInChannels, int numOutChannels, bool isBypassed)
 | 
			
		||||
    {
 | 
			
		||||
        int ch;
 | 
			
		||||
        for (ch = 0; ch < numInChannels; ++ch)
 | 
			
		||||
        {
 | 
			
		||||
            using DstSampleType = AudioData::Pointer<AudioData::Float32, AudioData::NativeEndian, AudioData::NonInterleaved, AudioData::NonConst>;
 | 
			
		||||
            using SrcSampleType = AudioData::Pointer<AudioData::Float32, AudioData::NativeEndian, AudioData::Interleaved,    AudioData::Const>;
 | 
			
		||||
 | 
			
		||||
            DstSampleType dstData (scratchBuffer.getWritePointer (ch));
 | 
			
		||||
            SrcSampleType srcData (inBuffer + ch, numInChannels);
 | 
			
		||||
            dstData.convertSamples (srcData, bufferSize);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (; ch < numOutChannels; ++ch)
 | 
			
		||||
            scratchBuffer.clear (ch, 0, bufferSize);
 | 
			
		||||
 | 
			
		||||
        {
 | 
			
		||||
            const ScopedLock sl (pluginInstance->getCallbackLock());
 | 
			
		||||
 | 
			
		||||
            if (pluginInstance->isSuspended())
 | 
			
		||||
            {
 | 
			
		||||
                scratchBuffer.clear();
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                MidiBuffer mb;
 | 
			
		||||
 | 
			
		||||
                if (isBypassed)
 | 
			
		||||
                    pluginInstance->processBlockBypassed (scratchBuffer, mb);
 | 
			
		||||
                else
 | 
			
		||||
                    pluginInstance->processBlock (scratchBuffer, mb);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (ch = 0; ch < numOutChannels; ++ch)
 | 
			
		||||
        {
 | 
			
		||||
            using DstSampleType = AudioData::Pointer<AudioData::Float32, AudioData::NativeEndian, AudioData::Interleaved,    AudioData::NonConst>;
 | 
			
		||||
            using SrcSampleType = AudioData::Pointer<AudioData::Float32, AudioData::NativeEndian, AudioData::NonInterleaved, AudioData::Const>;
 | 
			
		||||
 | 
			
		||||
            DstSampleType dstData (outBuffer + ch, numOutChannels);
 | 
			
		||||
            SrcSampleType srcData (scratchBuffer.getReadPointer (ch));
 | 
			
		||||
            dstData.convertSamples (srcData, bufferSize);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //==============================================================================
 | 
			
		||||
    std::unique_ptr<AudioProcessor> pluginInstance;
 | 
			
		||||
    std::unique_ptr<AudioProcessorEditor> pluginInstanceEditor;
 | 
			
		||||
 | 
			
		||||
    int samplesPerBlock = 1024;
 | 
			
		||||
    StringArray parameterDescriptions;
 | 
			
		||||
 | 
			
		||||
    AudioBuffer<float> scratchBuffer;
 | 
			
		||||
 | 
			
		||||
    LegacyAudioParametersWrapper juceParameters;
 | 
			
		||||
 | 
			
		||||
    //==============================================================================
 | 
			
		||||
    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioProcessorUnityWrapper)
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//==============================================================================
 | 
			
		||||
HashMap<int, AudioProcessorUnityWrapper*>& getWrapperMap()
 | 
			
		||||
{
 | 
			
		||||
    static HashMap<int, AudioProcessorUnityWrapper*> wrapperMap;
 | 
			
		||||
    return wrapperMap;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void onWrapperCreation (AudioProcessorUnityWrapper* wrapperToAdd)
 | 
			
		||||
{
 | 
			
		||||
    getWrapperMap().set (std::abs (Random::getSystemRandom().nextInt (65536)), wrapperToAdd);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void onWrapperDeletion (AudioProcessorUnityWrapper* wrapperToRemove)
 | 
			
		||||
{
 | 
			
		||||
    getWrapperMap().removeValue (wrapperToRemove);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//==============================================================================
 | 
			
		||||
namespace UnityCallbacks
 | 
			
		||||
{
 | 
			
		||||
    int UNITY_INTERFACE_API createCallback (UnityAudioEffectState* state)
 | 
			
		||||
    {
 | 
			
		||||
        auto* pluginInstance = new AudioProcessorUnityWrapper (false);
 | 
			
		||||
        pluginInstance->create (state);
 | 
			
		||||
 | 
			
		||||
        state->effectData = pluginInstance;
 | 
			
		||||
 | 
			
		||||
        onWrapperCreation (pluginInstance);
 | 
			
		||||
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int UNITY_INTERFACE_API releaseCallback (UnityAudioEffectState* state)
 | 
			
		||||
    {
 | 
			
		||||
        auto* pluginInstance = state->getEffectData<AudioProcessorUnityWrapper>();
 | 
			
		||||
        pluginInstance->release();
 | 
			
		||||
 | 
			
		||||
        onWrapperDeletion (pluginInstance);
 | 
			
		||||
        delete pluginInstance;
 | 
			
		||||
 | 
			
		||||
        if (getWrapperMap().size() == 0)
 | 
			
		||||
            shutdownJuce_GUI();
 | 
			
		||||
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int UNITY_INTERFACE_API resetCallback (UnityAudioEffectState* state)
 | 
			
		||||
    {
 | 
			
		||||
        auto* pluginInstance = state->getEffectData<AudioProcessorUnityWrapper>();
 | 
			
		||||
        pluginInstance->reset();
 | 
			
		||||
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int UNITY_INTERFACE_API setPositionCallback (UnityAudioEffectState* state, unsigned int pos)
 | 
			
		||||
    {
 | 
			
		||||
        ignoreUnused (state, pos);
 | 
			
		||||
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int UNITY_INTERFACE_API setFloatParameterCallback (UnityAudioEffectState* state, int index, float value)
 | 
			
		||||
    {
 | 
			
		||||
        auto* pluginInstance = state->getEffectData<AudioProcessorUnityWrapper>();
 | 
			
		||||
        pluginInstance->setParameter (index, value);
 | 
			
		||||
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int UNITY_INTERFACE_API getFloatParameterCallback (UnityAudioEffectState* state, int index, float* value, char* valueStr)
 | 
			
		||||
    {
 | 
			
		||||
        auto* pluginInstance = state->getEffectData<AudioProcessorUnityWrapper>();
 | 
			
		||||
        *value = pluginInstance->getParameter (index);
 | 
			
		||||
 | 
			
		||||
        strncpy (valueStr, pluginInstance->getParameterString (index).toRawUTF8(), 15);
 | 
			
		||||
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int UNITY_INTERFACE_API getFloatBufferCallback (UnityAudioEffectState* state, const char* name, float* buffer, int numSamples)
 | 
			
		||||
    {
 | 
			
		||||
        ignoreUnused (numSamples);
 | 
			
		||||
 | 
			
		||||
        auto nameStr = String (name);
 | 
			
		||||
 | 
			
		||||
        if (nameStr == "Editor")
 | 
			
		||||
        {
 | 
			
		||||
            auto* pluginInstance = state->getEffectData<AudioProcessorUnityWrapper>();
 | 
			
		||||
 | 
			
		||||
            buffer[0] = pluginInstance->hasEditor() ? 1.0f : 0.0f;
 | 
			
		||||
        }
 | 
			
		||||
        else if (nameStr == "ID")
 | 
			
		||||
        {
 | 
			
		||||
            auto* pluginInstance = state->getEffectData<AudioProcessorUnityWrapper>();
 | 
			
		||||
 | 
			
		||||
            for (HashMap<int, AudioProcessorUnityWrapper*>::Iterator i (getWrapperMap()); i.next();)
 | 
			
		||||
            {
 | 
			
		||||
                if (i.getValue() == pluginInstance)
 | 
			
		||||
                {
 | 
			
		||||
                    buffer[0] = (float) i.getKey();
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
        else if (nameStr == "Size")
 | 
			
		||||
        {
 | 
			
		||||
            auto* pluginInstance = state->getEffectData<AudioProcessorUnityWrapper>();
 | 
			
		||||
 | 
			
		||||
            auto& editor = pluginInstance->getEditorPeer().getEditor();
 | 
			
		||||
 | 
			
		||||
            buffer[0] = (float) editor.getBounds().getWidth();
 | 
			
		||||
            buffer[1] = (float) editor.getBounds().getHeight();
 | 
			
		||||
            buffer[2] = (float) editor.getConstrainer()->getMinimumWidth();
 | 
			
		||||
            buffer[3] = (float) editor.getConstrainer()->getMinimumHeight();
 | 
			
		||||
            buffer[4] = (float) editor.getConstrainer()->getMaximumWidth();
 | 
			
		||||
            buffer[5] = (float) editor.getConstrainer()->getMaximumHeight();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int UNITY_INTERFACE_API processCallback (UnityAudioEffectState* state, float* inBuffer, float* outBuffer,
 | 
			
		||||
                                             unsigned int bufferSize, int numInChannels, int numOutChannels)
 | 
			
		||||
    {
 | 
			
		||||
        auto* pluginInstance = state->getEffectData<AudioProcessorUnityWrapper>();
 | 
			
		||||
 | 
			
		||||
        if (pluginInstance != nullptr)
 | 
			
		||||
        {
 | 
			
		||||
            auto isPlaying = ((state->flags & stateIsPlaying) != 0);
 | 
			
		||||
            auto isMuted   = ((state->flags & stateIsMuted)   != 0);
 | 
			
		||||
            auto isPaused  = ((state->flags & stateIsPaused)  != 0);
 | 
			
		||||
 | 
			
		||||
            auto bypassed = ! isPlaying || (isMuted || isPaused);
 | 
			
		||||
 | 
			
		||||
            pluginInstance->process (inBuffer, outBuffer, static_cast<int> (bufferSize), numInChannels, numOutChannels, bypassed);
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            FloatVectorOperations::clear (outBuffer, static_cast<int> (bufferSize) * numOutChannels);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//==============================================================================
 | 
			
		||||
static void declareEffect (UnityAudioEffectDefinition& definition)
 | 
			
		||||
{
 | 
			
		||||
    memset (&definition, 0, sizeof (definition));
 | 
			
		||||
 | 
			
		||||
    std::unique_ptr<AudioProcessorUnityWrapper> wrapper = std::make_unique<AudioProcessorUnityWrapper> (true);
 | 
			
		||||
 | 
			
		||||
    String name (JucePlugin_Name);
 | 
			
		||||
    if (! name.startsWithIgnoreCase ("audioplugin"))
 | 
			
		||||
        name = "audioplugin_" + name;
 | 
			
		||||
 | 
			
		||||
    strcpy (definition.name, name.toRawUTF8());
 | 
			
		||||
 | 
			
		||||
    definition.structSize = sizeof (UnityAudioEffectDefinition);
 | 
			
		||||
    definition.parameterStructSize = sizeof (UnityAudioParameterDefinition);
 | 
			
		||||
 | 
			
		||||
    definition.apiVersion = UNITY_AUDIO_PLUGIN_API_VERSION;
 | 
			
		||||
    definition.pluginVersion = JucePlugin_VersionCode;
 | 
			
		||||
 | 
			
		||||
    // effects must set this to 0, generators > 0
 | 
			
		||||
    definition.channels = (wrapper->getNumInputChannels() != 0 ? 0
 | 
			
		||||
                                                               : static_cast<uint32> (wrapper->getNumOutputChannels()));
 | 
			
		||||
 | 
			
		||||
    wrapper->declareParameters (definition);
 | 
			
		||||
 | 
			
		||||
    definition.create            = UnityCallbacks::createCallback;
 | 
			
		||||
    definition.release           = UnityCallbacks::releaseCallback;
 | 
			
		||||
    definition.reset             = UnityCallbacks::resetCallback;
 | 
			
		||||
    definition.setPosition       = UnityCallbacks::setPositionCallback;
 | 
			
		||||
    definition.process           = UnityCallbacks::processCallback;
 | 
			
		||||
    definition.setFloatParameter = UnityCallbacks::setFloatParameterCallback;
 | 
			
		||||
    definition.getFloatParameter = UnityCallbacks::getFloatParameterCallback;
 | 
			
		||||
    definition.getFloatBuffer    = UnityCallbacks::getFloatBufferCallback;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace juce
 | 
			
		||||
 | 
			
		||||
UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API UnityGetAudioEffectDefinitions (UnityAudioEffectDefinition*** definitionsPtr)
 | 
			
		||||
{
 | 
			
		||||
    if (juce::getWrapperMap().size() == 0)
 | 
			
		||||
        juce::initialiseJuce_GUI();
 | 
			
		||||
 | 
			
		||||
    static bool hasInitialised = false;
 | 
			
		||||
 | 
			
		||||
    if (! hasInitialised)
 | 
			
		||||
    {
 | 
			
		||||
        juce::PluginHostType::jucePlugInClientCurrentWrapperType = juce::AudioProcessor::wrapperType_Unity;
 | 
			
		||||
        juce::juce_createUnityPeerFn = juce::createUnityPeer;
 | 
			
		||||
 | 
			
		||||
        hasInitialised = true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    auto* definition = new UnityAudioEffectDefinition();
 | 
			
		||||
    juce::declareEffect (*definition);
 | 
			
		||||
 | 
			
		||||
    *definitionsPtr = &definition;
 | 
			
		||||
 | 
			
		||||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//==============================================================================
 | 
			
		||||
static juce::ModifierKeys unityModifiersToJUCE (UnityEventModifiers mods, bool mouseDown, int mouseButton = -1)
 | 
			
		||||
{
 | 
			
		||||
    int flags = 0;
 | 
			
		||||
 | 
			
		||||
    if (mouseDown)
 | 
			
		||||
    {
 | 
			
		||||
        if (mouseButton == 0)
 | 
			
		||||
            flags |= juce::ModifierKeys::leftButtonModifier;
 | 
			
		||||
        else if (mouseButton == 1)
 | 
			
		||||
            flags |= juce::ModifierKeys::rightButtonModifier;
 | 
			
		||||
        else if (mouseButton == 2)
 | 
			
		||||
            flags |= juce::ModifierKeys::middleButtonModifier;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (mods == 0)
 | 
			
		||||
        return flags;
 | 
			
		||||
 | 
			
		||||
    if ((mods & UnityEventModifiers::shift) != 0)        flags |= juce::ModifierKeys::shiftModifier;
 | 
			
		||||
    if ((mods & UnityEventModifiers::control) != 0)      flags |= juce::ModifierKeys::ctrlModifier;
 | 
			
		||||
    if ((mods & UnityEventModifiers::alt) != 0)          flags |= juce::ModifierKeys::altModifier;
 | 
			
		||||
    if ((mods & UnityEventModifiers::command) != 0)      flags |= juce::ModifierKeys::commandModifier;
 | 
			
		||||
 | 
			
		||||
    return { flags };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//==============================================================================
 | 
			
		||||
static juce::AudioProcessorUnityWrapper* getWrapperChecked (int id)
 | 
			
		||||
{
 | 
			
		||||
    auto* wrapper = juce::getWrapperMap()[id];
 | 
			
		||||
    jassert (wrapper != nullptr);
 | 
			
		||||
 | 
			
		||||
    return wrapper;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//==============================================================================
 | 
			
		||||
static void UNITY_INTERFACE_API onRenderEvent (int id)
 | 
			
		||||
{
 | 
			
		||||
    getWrapperChecked (id)->getEditorPeer().triggerAsyncUpdate();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
UNITY_INTERFACE_EXPORT renderCallback UNITY_INTERFACE_API getRenderCallback()
 | 
			
		||||
{
 | 
			
		||||
    return onRenderEvent;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API unityInitialiseTexture (int id, void* data, int w, int h)
 | 
			
		||||
{
 | 
			
		||||
    getWrapperChecked (id)->getEditorPeer().setPixelDataHandle (reinterpret_cast<juce::uint8*> (data), w, h);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API unityMouseDown (int id, float x, float y, UnityEventModifiers unityMods, int button)
 | 
			
		||||
{
 | 
			
		||||
    getWrapperChecked (id)->getEditorPeer().forwardMouseEvent ({ x, y }, unityModifiersToJUCE (unityMods, true, button));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API unityMouseDrag (int id, float x, float y, UnityEventModifiers unityMods, int button)
 | 
			
		||||
{
 | 
			
		||||
    getWrapperChecked (id)->getEditorPeer().forwardMouseEvent ({ x, y }, unityModifiersToJUCE (unityMods, true, button));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API unityMouseUp (int id, float x, float y, UnityEventModifiers unityMods)
 | 
			
		||||
{
 | 
			
		||||
    getWrapperChecked (id)->getEditorPeer().forwardMouseEvent ({ x, y }, unityModifiersToJUCE (unityMods, false));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API unityKeyEvent (int id, int code, UnityEventModifiers mods, const char* name)
 | 
			
		||||
{
 | 
			
		||||
    getWrapperChecked (id)->getEditorPeer().forwardKeyPress (code, name, unityModifiersToJUCE (mods, false));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API unitySetScreenBounds (int id, float x, float y, float w, float h)
 | 
			
		||||
{
 | 
			
		||||
    getWrapperChecked (id)->getEditorPeer().getEditor().setBounds ({ (int) x, (int) y, (int) w, (int) h });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//==============================================================================
 | 
			
		||||
#if JUCE_WINDOWS
 | 
			
		||||
 extern "C" BOOL WINAPI DllMain (HINSTANCE instance, DWORD reason, LPVOID)
 | 
			
		||||
 {
 | 
			
		||||
     if (reason == DLL_PROCESS_ATTACH)
 | 
			
		||||
         juce::Process::setCurrentModuleInstanceHandle (instance);
 | 
			
		||||
 | 
			
		||||
     return true;
 | 
			
		||||
 }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@ -27,14 +27,14 @@
 | 
			
		||||
namespace juce
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
/** An interface to allow an AudioProcessor to receive VST specific calls from
 | 
			
		||||
/** An interface to allow an AudioProcessor to send and receive VST specific calls from
 | 
			
		||||
    the host.
 | 
			
		||||
 | 
			
		||||
    @tags{Audio}
 | 
			
		||||
*/
 | 
			
		||||
struct VSTCallbackHandler
 | 
			
		||||
{
 | 
			
		||||
    virtual ~VSTCallbackHandler() {}
 | 
			
		||||
    virtual ~VSTCallbackHandler() = default;
 | 
			
		||||
 | 
			
		||||
    /** This is called by the VST plug-in wrapper when it receives unhandled
 | 
			
		||||
        plug-in "can do" calls from the host.
 | 
			
		||||
@ -55,6 +55,22 @@ struct VSTCallbackHandler
 | 
			
		||||
                                                             pointer_sized_int value,
 | 
			
		||||
                                                             void* ptr,
 | 
			
		||||
                                                             float opt) = 0;
 | 
			
		||||
 | 
			
		||||
    // Note: VS2013 prevents a "using" declaration here
 | 
			
		||||
    /** The host callback function type. */
 | 
			
		||||
    typedef pointer_sized_int (VstHostCallbackType) (int32 opcode,
 | 
			
		||||
                                                     int32 index,
 | 
			
		||||
                                                     pointer_sized_int value,
 | 
			
		||||
                                                     void* ptr,
 | 
			
		||||
                                                     float opt);
 | 
			
		||||
 | 
			
		||||
    /** This is called once by the VST plug-in wrapper after its constructor.
 | 
			
		||||
        You can use the supplied function to query the VST host.
 | 
			
		||||
    */
 | 
			
		||||
    virtual void handleVstHostCallbackAvailable (std::function<VstHostCallbackType>&& callback)
 | 
			
		||||
    {
 | 
			
		||||
        ignoreUnused (callback);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace juce
 | 
			
		||||
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@ -50,7 +50,10 @@
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if JUCE_VST3_CAN_REPLACE_VST2
 | 
			
		||||
#include "../../juce_audio_processors/format_types/juce_VSTInterface.h"
 | 
			
		||||
namespace Vst2
 | 
			
		||||
{
 | 
			
		||||
#include "pluginterfaces/vst2.x/vstfxstore.h"
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef JUCE_VST3_EMULATE_MIDI_CC_WITH_PARAMETERS
 | 
			
		||||
@ -83,7 +86,6 @@ using namespace Steinberg;
 | 
			
		||||
 | 
			
		||||
  extern JUCE_API void* attachComponentToWindowRefVST (Component*, void* parentWindowOrView, bool isNSView);
 | 
			
		||||
  extern JUCE_API void detachComponentFromWindowRefVST (Component*, void* nsWindow, bool isNSView);
 | 
			
		||||
  extern JUCE_API void setNativeHostWindowSizeVST (void* window, Component*, int newWidth, int newHeight, bool isNSView);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//==============================================================================
 | 
			
		||||
@ -123,6 +125,11 @@ public:
 | 
			
		||||
        return getParamForVSTParamID (bypassParamID);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    static Vst::UnitID getUnitID (const AudioProcessorParameterGroup* group)
 | 
			
		||||
    {
 | 
			
		||||
        return group == nullptr ? Vst::kRootUnitId : group->getID().hashCode();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int getNumParameters() const noexcept             { return vstParamIDs.size(); }
 | 
			
		||||
    bool isUsingManagedParameters() const noexcept    { return juceParameters.isUsingManagedParameters(); }
 | 
			
		||||
 | 
			
		||||
@ -191,7 +198,7 @@ private:
 | 
			
		||||
            {
 | 
			
		||||
                // we need to remain backward compatible with the old bypass id
 | 
			
		||||
                if (vst3WrapperProvidedBypassParam)
 | 
			
		||||
                    vstParamID = static_cast<Vst::ParamID> (isUsingManagedParameters() ? paramBypass : numParameters);
 | 
			
		||||
                    vstParamID = static_cast<Vst::ParamID> ((isUsingManagedParameters() && ! forceLegacyParamIDs) ? paramBypass : numParameters);
 | 
			
		||||
 | 
			
		||||
                bypassParamID = vstParamID;
 | 
			
		||||
            }
 | 
			
		||||
@ -327,10 +334,12 @@ public:
 | 
			
		||||
    struct Param  : public Vst::Parameter
 | 
			
		||||
    {
 | 
			
		||||
        Param (JuceVST3EditController& editController, AudioProcessorParameter& p,
 | 
			
		||||
               Vst::ParamID vstParamID, bool isBypassParameter, bool forceLegacyParamIDs)
 | 
			
		||||
               Vst::ParamID vstParamID, Vst::UnitID vstUnitID,
 | 
			
		||||
               bool isBypassParameter, bool forceLegacyParamIDs)
 | 
			
		||||
            : owner (editController), param (p)
 | 
			
		||||
        {
 | 
			
		||||
            info.id = vstParamID;
 | 
			
		||||
            info.unitId = vstUnitID;
 | 
			
		||||
 | 
			
		||||
            toString128 (info.title,      param.getName (128));
 | 
			
		||||
            toString128 (info.shortTitle, param.getName (8));
 | 
			
		||||
@ -346,7 +355,6 @@ public:
 | 
			
		||||
 | 
			
		||||
            info.defaultNormalizedValue = param.getDefaultValue();
 | 
			
		||||
            jassert (info.defaultNormalizedValue >= 0 && info.defaultNormalizedValue <= 1.0f);
 | 
			
		||||
            info.unitId = Vst::kRootUnitId;
 | 
			
		||||
 | 
			
		||||
            // Is this a meter?
 | 
			
		||||
            if (((param.getCategory() & 0xffff0000) >> 16) == 2)
 | 
			
		||||
@ -711,6 +719,7 @@ private:
 | 
			
		||||
 | 
			
		||||
    //==============================================================================
 | 
			
		||||
    Atomic<int> vst3IsPlaying { 0 };
 | 
			
		||||
    float lastScaleFactorReceived = 1.0f;
 | 
			
		||||
 | 
			
		||||
    void setupParameters()
 | 
			
		||||
    {
 | 
			
		||||
@ -737,8 +746,10 @@ private:
 | 
			
		||||
                {
 | 
			
		||||
                    auto vstParamID = audioProcessor->getVSTParamIDForIndex (i);
 | 
			
		||||
                    auto* juceParam = audioProcessor->getParamForVSTParamID (vstParamID);
 | 
			
		||||
                    auto* parameterGroup = pluginInstance->parameterTree.getGroupsForParameter (juceParam).getLast();
 | 
			
		||||
                    auto unitID = JuceAudioProcessor::getUnitID (parameterGroup);
 | 
			
		||||
 | 
			
		||||
                    parameters.addParameter (new Param (*this, *juceParam, vstParamID,
 | 
			
		||||
                    parameters.addParameter (new Param (*this, *juceParam, vstParamID, unitID,
 | 
			
		||||
                                                        (vstParamID == audioProcessor->bypassParamID), forceLegacyParamIDs));
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
@ -797,7 +808,14 @@ private:
 | 
			
		||||
          : Vst::EditorView (&ec, nullptr),
 | 
			
		||||
            owner (&ec), pluginInstance (p)
 | 
			
		||||
        {
 | 
			
		||||
            editorScaleFactor = ec.lastScaleFactorReceived;
 | 
			
		||||
 | 
			
		||||
            component.reset (new ContentWrapperComponent (*this, p));
 | 
			
		||||
 | 
			
		||||
           #if JUCE_MAC
 | 
			
		||||
            if (getHostType().type == PluginHostType::SteinbergCubase10)
 | 
			
		||||
                cubase10Workaround.reset (new Cubase10WindowResizeWorkaround (*this));
 | 
			
		||||
           #endif
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        tresult PLUGIN_API queryInterface (const TUID targetIID, void** obj) override
 | 
			
		||||
@ -841,6 +859,10 @@ private:
 | 
			
		||||
            macHostWindow = juce::attachComponentToWindowRefVST (component.get(), parent, isNSView);
 | 
			
		||||
           #endif
 | 
			
		||||
 | 
			
		||||
           #if ! JUCE_MAC
 | 
			
		||||
            setContentScaleFactor ((Steinberg::IPlugViewContentScaleSupport::ScaleFactor) editorScaleFactor);
 | 
			
		||||
           #endif
 | 
			
		||||
 | 
			
		||||
            component->resizeHostWindow();
 | 
			
		||||
            systemWindow = parent;
 | 
			
		||||
            attachedToParent();
 | 
			
		||||
@ -880,10 +902,41 @@ private:
 | 
			
		||||
 | 
			
		||||
                if (component != nullptr)
 | 
			
		||||
                {
 | 
			
		||||
                    component->setSize (rect.getWidth(), rect.getHeight());
 | 
			
		||||
                    auto w = rect.getWidth();
 | 
			
		||||
                    auto h = rect.getHeight();
 | 
			
		||||
 | 
			
		||||
                   #if JUCE_WINDOWS && JUCE_WIN_PER_MONITOR_DPI_AWARE
 | 
			
		||||
                    w = roundToInt (w / editorScaleFactor);
 | 
			
		||||
                    h = roundToInt (h / editorScaleFactor);
 | 
			
		||||
 | 
			
		||||
                    if (getHostType().type == PluginHostType::SteinbergCubase10)
 | 
			
		||||
                    {
 | 
			
		||||
                        auto integerScaleFactor = (int) std::round (editorScaleFactor);
 | 
			
		||||
 | 
			
		||||
                        // Workaround for Cubase 10 sending double-scaled bounds when opening editor
 | 
			
		||||
                        if (isWithin ((int) w, component->getWidth() * integerScaleFactor, 2)
 | 
			
		||||
                            && isWithin ((int) h, component->getHeight() * integerScaleFactor, 2))
 | 
			
		||||
                        {
 | 
			
		||||
                            w /= integerScaleFactor;
 | 
			
		||||
                            h /= integerScaleFactor;
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                   #endif
 | 
			
		||||
 | 
			
		||||
                    component->setSize (w, h);
 | 
			
		||||
 | 
			
		||||
                   #if JUCE_MAC
 | 
			
		||||
                    if (cubase10Workaround != nullptr)
 | 
			
		||||
                        cubase10Workaround->triggerAsyncUpdate();
 | 
			
		||||
                    else
 | 
			
		||||
                   #endif
 | 
			
		||||
                    if (auto* peer = component->getPeer())
 | 
			
		||||
                        peer->updateBounds();
 | 
			
		||||
 | 
			
		||||
                   #if JUCE_WINDOWS && JUCE_WIN_PER_MONITOR_DPI_AWARE
 | 
			
		||||
                    if (getHostType().type == PluginHostType::SteinbergCubase10)
 | 
			
		||||
                        component->resizeHostWindow();
 | 
			
		||||
                   #endif
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                return kResultTrue;
 | 
			
		||||
@ -897,7 +950,16 @@ private:
 | 
			
		||||
        {
 | 
			
		||||
            if (size != nullptr && component != nullptr)
 | 
			
		||||
            {
 | 
			
		||||
                *size = ViewRect (0, 0, component->getWidth(), component->getHeight());
 | 
			
		||||
                auto w = component->getWidth();
 | 
			
		||||
                auto h = component->getHeight();
 | 
			
		||||
 | 
			
		||||
               #if JUCE_WINDOWS && JUCE_WIN_PER_MONITOR_DPI_AWARE
 | 
			
		||||
                w = roundToInt (w * editorScaleFactor);
 | 
			
		||||
                h = roundToInt (h * editorScaleFactor);
 | 
			
		||||
               #endif
 | 
			
		||||
 | 
			
		||||
                *size = ViewRect (0, 0, w, h);
 | 
			
		||||
 | 
			
		||||
                return kResultTrue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@ -919,17 +981,67 @@ private:
 | 
			
		||||
            {
 | 
			
		||||
                if (auto* editor = component->pluginEditor.get())
 | 
			
		||||
                {
 | 
			
		||||
                    // checkSizeConstraint
 | 
			
		||||
                    auto juceRect = editor->getLocalArea (component.get(), Rectangle<int>::leftTopRightBottom (rectToCheck->left, rectToCheck->top,
 | 
			
		||||
                                                                                                               rectToCheck->right, rectToCheck->bottom));
 | 
			
		||||
                    if (auto* constrainer = editor->getConstrainer())
 | 
			
		||||
                    {
 | 
			
		||||
                        Rectangle<int> limits (0, 0, constrainer->getMaximumWidth(), constrainer->getMaximumHeight());
 | 
			
		||||
                        constrainer->checkBounds (juceRect, editor->getBounds(), limits, false, false, false, false);
 | 
			
		||||
                        auto minW = (double) constrainer->getMinimumWidth();
 | 
			
		||||
                        auto maxW = (double) constrainer->getMaximumWidth();
 | 
			
		||||
                        auto minH = (double) constrainer->getMinimumHeight();
 | 
			
		||||
                        auto maxH = (double) constrainer->getMaximumHeight();
 | 
			
		||||
 | 
			
		||||
                        juceRect = component->getLocalArea (editor, juceRect);
 | 
			
		||||
                        rectToCheck->right  = rectToCheck->left + juceRect.getWidth();
 | 
			
		||||
                        rectToCheck->bottom = rectToCheck->top  + juceRect.getHeight();
 | 
			
		||||
                        auto width  = (double) (rectToCheck->right - rectToCheck->left);
 | 
			
		||||
                        auto height = (double) (rectToCheck->bottom - rectToCheck->top);
 | 
			
		||||
 | 
			
		||||
                       #if JUCE_WINDOWS && JUCE_WIN_PER_MONITOR_DPI_AWARE
 | 
			
		||||
                        width  /= editorScaleFactor;
 | 
			
		||||
                        height /= editorScaleFactor;
 | 
			
		||||
                       #endif
 | 
			
		||||
 | 
			
		||||
                        width  = jlimit (minW, maxW, width);
 | 
			
		||||
                        height = jlimit (minH, maxH, height);
 | 
			
		||||
 | 
			
		||||
                        auto aspectRatio = constrainer->getFixedAspectRatio();
 | 
			
		||||
 | 
			
		||||
                        if (aspectRatio != 0.0)
 | 
			
		||||
                        {
 | 
			
		||||
                            bool adjustWidth = (width / height > aspectRatio);
 | 
			
		||||
 | 
			
		||||
                            if (getHostType().type == PluginHostType::SteinbergCubase9)
 | 
			
		||||
                            {
 | 
			
		||||
                                if (editor->getWidth() == width && editor->getHeight() != height)
 | 
			
		||||
                                    adjustWidth = true;
 | 
			
		||||
                                else if (editor->getHeight() == height && editor->getWidth() != width)
 | 
			
		||||
                                    adjustWidth = false;
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
                            if (adjustWidth)
 | 
			
		||||
                            {
 | 
			
		||||
                                width = height * aspectRatio;
 | 
			
		||||
 | 
			
		||||
                                if (width > maxW || width < minW)
 | 
			
		||||
                                {
 | 
			
		||||
                                    width = jlimit (minW, maxW, width);
 | 
			
		||||
                                    height = width / aspectRatio;
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                            else
 | 
			
		||||
                            {
 | 
			
		||||
                                height = width / aspectRatio;
 | 
			
		||||
 | 
			
		||||
                                if (height > maxH || height < minH)
 | 
			
		||||
                                {
 | 
			
		||||
                                    height = jlimit (minH, maxH, height);
 | 
			
		||||
                                    width = height * aspectRatio;
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                       #if JUCE_WINDOWS && JUCE_WIN_PER_MONITOR_DPI_AWARE
 | 
			
		||||
                        width  *= editorScaleFactor;
 | 
			
		||||
                        height *= editorScaleFactor;
 | 
			
		||||
                       #endif
 | 
			
		||||
 | 
			
		||||
                        rectToCheck->right  = rectToCheck->left + roundToInt (width);
 | 
			
		||||
                        rectToCheck->bottom = rectToCheck->top  + roundToInt (height);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
@ -942,17 +1054,40 @@ private:
 | 
			
		||||
 | 
			
		||||
        tresult PLUGIN_API setContentScaleFactor (Steinberg::IPlugViewContentScaleSupport::ScaleFactor factor) override
 | 
			
		||||
        {
 | 
			
		||||
           #if (JUCE_MAC || JUCE_IOS)
 | 
			
		||||
            ignoreUnused (factor);
 | 
			
		||||
           #else
 | 
			
		||||
            if (auto* editor = component->pluginEditor.get())
 | 
			
		||||
           #if ! JUCE_MAC
 | 
			
		||||
            // Cubase 10 doesn't support non-integer scale factors...
 | 
			
		||||
            if (getHostType().type == PluginHostType::SteinbergCubase10)
 | 
			
		||||
            {
 | 
			
		||||
                editor->setScaleFactor (factor);
 | 
			
		||||
                return kResultTrue;
 | 
			
		||||
                if (component.get() != nullptr)
 | 
			
		||||
                    if (auto* peer = component->getPeer())
 | 
			
		||||
                        factor = static_cast<Steinberg::IPlugViewContentScaleSupport::ScaleFactor> (peer->getPlatformScaleFactor());
 | 
			
		||||
            }
 | 
			
		||||
           #endif
 | 
			
		||||
 | 
			
		||||
            if (! approximatelyEqual ((float) factor, editorScaleFactor))
 | 
			
		||||
            {
 | 
			
		||||
                editorScaleFactor = (float) factor;
 | 
			
		||||
 | 
			
		||||
                if (auto* o = owner.get())
 | 
			
		||||
                    o->lastScaleFactorReceived = editorScaleFactor;
 | 
			
		||||
 | 
			
		||||
                if (component == nullptr)
 | 
			
		||||
                    return kResultFalse;
 | 
			
		||||
 | 
			
		||||
               #if JUCE_WINDOWS && ! JUCE_WIN_PER_MONITOR_DPI_AWARE
 | 
			
		||||
                if (auto* ed = component->pluginEditor.get())
 | 
			
		||||
                    ed->setScaleFactor ((float) factor);
 | 
			
		||||
               #endif
 | 
			
		||||
 | 
			
		||||
                component->resizeHostWindow();
 | 
			
		||||
                component->setTopLeftPosition (0, 0);
 | 
			
		||||
                component->repaint();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return kResultTrue;
 | 
			
		||||
           #else
 | 
			
		||||
            ignoreUnused (factor);
 | 
			
		||||
            return kResultFalse;
 | 
			
		||||
           #endif
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
@ -969,8 +1104,8 @@ private:
 | 
			
		||||
        struct ContentWrapperComponent  : public Component
 | 
			
		||||
        {
 | 
			
		||||
            ContentWrapperComponent (JuceVST3Editor& editor, AudioProcessor& plugin)
 | 
			
		||||
               : pluginEditor (plugin.createEditorIfNeeded()),
 | 
			
		||||
                 owner (editor)
 | 
			
		||||
                : pluginEditor (plugin.createEditorIfNeeded()),
 | 
			
		||||
                  owner (editor)
 | 
			
		||||
            {
 | 
			
		||||
                setOpaque (true);
 | 
			
		||||
                setBroughtToFrontOnMouseClick (true);
 | 
			
		||||
@ -1032,10 +1167,27 @@ private:
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
           #if JUCE_WINDOWS && JUCE_WIN_PER_MONITOR_DPI_AWARE
 | 
			
		||||
            void checkScaleFactorIsCorrect()
 | 
			
		||||
            {
 | 
			
		||||
                if (auto* peer = pluginEditor->getPeer())
 | 
			
		||||
                {
 | 
			
		||||
                    auto peerScaleFactor = (float) peer->getPlatformScaleFactor();
 | 
			
		||||
 | 
			
		||||
                    if (! approximatelyEqual (peerScaleFactor, owner.editorScaleFactor))
 | 
			
		||||
                        owner.setContentScaleFactor (peerScaleFactor);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
           #endif
 | 
			
		||||
 | 
			
		||||
            void resized() override
 | 
			
		||||
            {
 | 
			
		||||
                if (pluginEditor != nullptr)
 | 
			
		||||
                {
 | 
			
		||||
                   #if JUCE_WINDOWS && JUCE_WIN_PER_MONITOR_DPI_AWARE
 | 
			
		||||
                    checkScaleFactorIsCorrect();
 | 
			
		||||
                   #endif
 | 
			
		||||
 | 
			
		||||
                    if (! isResizingParentToFitChild)
 | 
			
		||||
                    {
 | 
			
		||||
                        lastBounds = getLocalBounds();
 | 
			
		||||
@ -1074,17 +1226,21 @@ private:
 | 
			
		||||
 | 
			
		||||
                   #if JUCE_WINDOWS
 | 
			
		||||
                    setSize (w, h);
 | 
			
		||||
                   #else
 | 
			
		||||
                    if (owner.macHostWindow != nullptr && ! (host.isWavelab() || host.isReaper() || host.isBitwigStudio()))
 | 
			
		||||
                        juce::setNativeHostWindowSizeVST (owner.macHostWindow, this, w, h, owner.isNSView);
 | 
			
		||||
                   #endif
 | 
			
		||||
 | 
			
		||||
                    if (owner.plugFrame != nullptr)
 | 
			
		||||
                    {
 | 
			
		||||
                       #if JUCE_WINDOWS && JUCE_WIN_PER_MONITOR_DPI_AWARE
 | 
			
		||||
                        w = roundToInt (w * owner.editorScaleFactor);
 | 
			
		||||
                        h = roundToInt (h * owner.editorScaleFactor);
 | 
			
		||||
                       #endif
 | 
			
		||||
 | 
			
		||||
                        ViewRect newSize (0, 0, w, h);
 | 
			
		||||
                        isResizingParentToFitChild = true;
 | 
			
		||||
                        owner.plugFrame->resizeView (&owner, &newSize);
 | 
			
		||||
                        isResizingParentToFitChild = false;
 | 
			
		||||
 | 
			
		||||
                        {
 | 
			
		||||
                            const ScopedValueSetter<bool> resizingParentSetter (isResizingParentToFitChild, true);
 | 
			
		||||
                            owner.plugFrame->resizeView (&owner, &newSize);
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                       #if JUCE_MAC
 | 
			
		||||
                        if (host.isWavelab() || host.isReaper())
 | 
			
		||||
@ -1118,8 +1274,27 @@ private:
 | 
			
		||||
       #if JUCE_MAC
 | 
			
		||||
        void* macHostWindow = nullptr;
 | 
			
		||||
        bool isNSView = false;
 | 
			
		||||
 | 
			
		||||
        // On macOS Cubase 10 resizes the host window after calling onSize() resulting in the peer
 | 
			
		||||
        // bounds being a step behind the plug-in. Calling updateBounds() asynchronously seems to fix things...
 | 
			
		||||
        struct Cubase10WindowResizeWorkaround  : public AsyncUpdater
 | 
			
		||||
        {
 | 
			
		||||
            Cubase10WindowResizeWorkaround (JuceVST3Editor& o)  : owner (o) {}
 | 
			
		||||
 | 
			
		||||
            void handleAsyncUpdate() override
 | 
			
		||||
            {
 | 
			
		||||
                if (auto* peer = owner.component->getPeer())
 | 
			
		||||
                    peer->updateBounds();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            JuceVST3Editor& owner;
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        std::unique_ptr<Cubase10WindowResizeWorkaround> cubase10Workaround;
 | 
			
		||||
       #endif
 | 
			
		||||
 | 
			
		||||
        float editorScaleFactor = 1.0f;
 | 
			
		||||
 | 
			
		||||
       #if JUCE_WINDOWS
 | 
			
		||||
        WindowsHooks hooks;
 | 
			
		||||
       #endif
 | 
			
		||||
@ -1163,6 +1338,7 @@ public:
 | 
			
		||||
        short configs[][2] = { JucePlugin_PreferredChannelConfigurations };
 | 
			
		||||
        const int numConfigs = sizeof (configs) / sizeof (short[2]);
 | 
			
		||||
 | 
			
		||||
        ignoreUnused (numConfigs);
 | 
			
		||||
        jassert (numConfigs > 0 && (configs[0][0] > 0 || configs[0][1] > 0));
 | 
			
		||||
 | 
			
		||||
        pluginInstance->setPlayConfigDetails (configs[0][0], configs[0][1], 44100.0, 1024);
 | 
			
		||||
@ -1173,6 +1349,8 @@ public:
 | 
			
		||||
        // and not AudioChannelSet::discreteChannels (2) etc.
 | 
			
		||||
        jassert (checkBusFormatsAreNotDiscrete());
 | 
			
		||||
 | 
			
		||||
        parameterGroups = pluginInstance->parameterTree.getSubgroups (true);
 | 
			
		||||
 | 
			
		||||
        comPluginInstance = new JuceAudioProcessor (pluginInstance);
 | 
			
		||||
 | 
			
		||||
        zerostruct (processContext);
 | 
			
		||||
@ -1440,16 +1618,16 @@ public:
 | 
			
		||||
 | 
			
		||||
    bool loadVST2CcnKBlock (const char* data, int size)
 | 
			
		||||
    {
 | 
			
		||||
        auto bank = (const vst2FxBank*) data;
 | 
			
		||||
        auto bank = (const Vst2::fxBank*) data;
 | 
			
		||||
 | 
			
		||||
        jassert ('CcnK' == htonl (bank->magic1));
 | 
			
		||||
        jassert ('FBCh' == htonl (bank->magic2));
 | 
			
		||||
        jassert (htonl (bank->version1) == 1 || htonl (bank->version1) == 2);
 | 
			
		||||
        jassert ('CcnK' == htonl (bank->chunkMagic));
 | 
			
		||||
        jassert ('FBCh' == htonl (bank->fxMagic));
 | 
			
		||||
        jassert (htonl (bank->version) == 1 || htonl (bank->version) == 2);
 | 
			
		||||
        jassert (JucePlugin_VSTUniqueID == htonl (bank->fxID));
 | 
			
		||||
 | 
			
		||||
        setStateInformation (bank->chunk,
 | 
			
		||||
                             jmin ((int) (size - (bank->chunk - data)),
 | 
			
		||||
                                   (int) htonl (bank->chunkSize)));
 | 
			
		||||
        setStateInformation (bank->content.data.chunk,
 | 
			
		||||
                             jmin ((int) (size - (bank->content.data.chunk - data)),
 | 
			
		||||
                                   (int) htonl (bank->content.data.size)));
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -1642,16 +1820,16 @@ public:
 | 
			
		||||
            return status;
 | 
			
		||||
 | 
			
		||||
        const int bankBlockSize = 160;
 | 
			
		||||
        vst2FxBank bank;
 | 
			
		||||
        Vst2::fxBank bank;
 | 
			
		||||
 | 
			
		||||
        zerostruct (bank);
 | 
			
		||||
        bank.magic1         = (int32) htonl ('CcnK');
 | 
			
		||||
        bank.size           = (int32) htonl (bankBlockSize - 8 + (unsigned int) mem.getSize());
 | 
			
		||||
        bank.magic2         = (int32) htonl ('FBCh');
 | 
			
		||||
        bank.version1       = (int32) htonl (2);
 | 
			
		||||
        bank.fxID           = (int32) htonl (JucePlugin_VSTUniqueID);
 | 
			
		||||
        bank.version2       = (int32) htonl (JucePlugin_VersionCode);
 | 
			
		||||
        bank.chunkSize      = (int32) htonl ((unsigned int) mem.getSize());
 | 
			
		||||
        bank.chunkMagic         = (int32) htonl ('CcnK');
 | 
			
		||||
        bank.byteSize           = (int32) htonl (bankBlockSize - 8 + (unsigned int) mem.getSize());
 | 
			
		||||
        bank.fxMagic            = (int32) htonl ('FBCh');
 | 
			
		||||
        bank.version            = (int32) htonl (2);
 | 
			
		||||
        bank.fxID               = (int32) htonl (JucePlugin_VSTUniqueID);
 | 
			
		||||
        bank.fxVersion          = (int32) htonl (JucePlugin_VersionCode);
 | 
			
		||||
        bank.content.data.size  = (int32) htonl ((unsigned int) mem.getSize());
 | 
			
		||||
 | 
			
		||||
        status = state->write (&bank, bankBlockSize);
 | 
			
		||||
 | 
			
		||||
@ -1665,7 +1843,7 @@ public:
 | 
			
		||||
    //==============================================================================
 | 
			
		||||
    Steinberg::int32 PLUGIN_API getUnitCount() override
 | 
			
		||||
    {
 | 
			
		||||
        return 1;
 | 
			
		||||
        return parameterGroups.size() + 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    tresult PLUGIN_API getUnitInfo (Steinberg::int32 unitIndex, Vst::UnitInfo& info) override
 | 
			
		||||
@ -1681,7 +1859,17 @@ public:
 | 
			
		||||
            return kResultTrue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        zerostruct (info);
 | 
			
		||||
        if (auto* group = parameterGroups[unitIndex - 1])
 | 
			
		||||
        {
 | 
			
		||||
            info.id             = JuceAudioProcessor::getUnitID (group);
 | 
			
		||||
            info.parentUnitId   = JuceAudioProcessor::getUnitID (group->getParent());
 | 
			
		||||
            info.programListId  = Vst::kNoProgramListId;
 | 
			
		||||
 | 
			
		||||
            toString128 (info.name, group->getName());
 | 
			
		||||
 | 
			
		||||
            return kResultTrue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return kResultFalse;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -1860,7 +2048,13 @@ public:
 | 
			
		||||
            {
 | 
			
		||||
                info.mediaType = Vst::kEvent;
 | 
			
		||||
                info.direction = dir;
 | 
			
		||||
 | 
			
		||||
               #ifdef JucePlugin_VSTNumMidiInputs
 | 
			
		||||
                info.channelCount = JucePlugin_VSTNumMidiInputs;
 | 
			
		||||
               #else
 | 
			
		||||
                info.channelCount = 16;
 | 
			
		||||
               #endif
 | 
			
		||||
 | 
			
		||||
                toString128 (info.name, TRANS("MIDI Input"));
 | 
			
		||||
                info.busType = Vst::kMain;
 | 
			
		||||
                return kResultTrue;
 | 
			
		||||
@ -1872,7 +2066,13 @@ public:
 | 
			
		||||
            {
 | 
			
		||||
                info.mediaType = Vst::kEvent;
 | 
			
		||||
                info.direction = dir;
 | 
			
		||||
 | 
			
		||||
               #ifdef JucePlugin_VSTNumMidiOutputs
 | 
			
		||||
                info.channelCount = JucePlugin_VSTNumMidiOutputs;
 | 
			
		||||
               #else
 | 
			
		||||
                info.channelCount = 16;
 | 
			
		||||
               #endif
 | 
			
		||||
 | 
			
		||||
                toString128 (info.name, TRANS("MIDI Output"));
 | 
			
		||||
                info.busType = Vst::kMain;
 | 
			
		||||
                return kResultTrue;
 | 
			
		||||
@ -2033,6 +2233,9 @@ public:
 | 
			
		||||
        if (tailLengthSeconds <= 0.0 || processSetup.sampleRate <= 0.0)
 | 
			
		||||
            return Vst::kNoTail;
 | 
			
		||||
 | 
			
		||||
        if (tailLengthSeconds == std::numeric_limits<double>::infinity())
 | 
			
		||||
            return Vst::kInfiniteTail;
 | 
			
		||||
 | 
			
		||||
        return (Steinberg::uint32) roundToIntAccurate (tailLengthSeconds * processSetup.sampleRate);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -2162,43 +2365,6 @@ public:
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    //==============================================================================
 | 
			
		||||
    Atomic<int> refCount { 1 };
 | 
			
		||||
 | 
			
		||||
    AudioProcessor* pluginInstance;
 | 
			
		||||
    ComSmartPtr<Vst::IHostApplication> host;
 | 
			
		||||
    ComSmartPtr<JuceAudioProcessor> comPluginInstance;
 | 
			
		||||
    ComSmartPtr<JuceVST3EditController> juceVST3EditController;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
        Since VST3 does not provide a way of knowing the buffer size and sample rate at any point,
 | 
			
		||||
        this object needs to be copied on every call to process() to be up-to-date...
 | 
			
		||||
    */
 | 
			
		||||
    Vst::ProcessContext processContext;
 | 
			
		||||
    Vst::ProcessSetup processSetup;
 | 
			
		||||
 | 
			
		||||
    MidiBuffer midiBuffer;
 | 
			
		||||
    Array<float*> channelListFloat;
 | 
			
		||||
    Array<double*> channelListDouble;
 | 
			
		||||
 | 
			
		||||
    AudioBuffer<float>  emptyBufferFloat;
 | 
			
		||||
    AudioBuffer<double> emptyBufferDouble;
 | 
			
		||||
 | 
			
		||||
   #if JucePlugin_WantsMidiInput
 | 
			
		||||
    bool isMidiInputBusEnabled = true;
 | 
			
		||||
   #else
 | 
			
		||||
    bool isMidiInputBusEnabled = false;
 | 
			
		||||
   #endif
 | 
			
		||||
 | 
			
		||||
   #if JucePlugin_ProducesMidiOutput
 | 
			
		||||
    bool isMidiOutputBusEnabled = true;
 | 
			
		||||
   #else
 | 
			
		||||
    bool isMidiOutputBusEnabled = false;
 | 
			
		||||
   #endif
 | 
			
		||||
 | 
			
		||||
    ScopedJuceInitialiser_GUI libraryInitialiser;
 | 
			
		||||
    static const char* kJucePrivateDataIdentifier;
 | 
			
		||||
 | 
			
		||||
    //==============================================================================
 | 
			
		||||
    template <typename FloatType>
 | 
			
		||||
    void processAudio (Vst::ProcessData& data, Array<FloatType*>& channelList)
 | 
			
		||||
@ -2410,9 +2576,51 @@ private:
 | 
			
		||||
 | 
			
		||||
        p.setRateAndBufferSizeDetails (sampleRate, bufferSize);
 | 
			
		||||
        p.prepareToPlay (sampleRate, bufferSize);
 | 
			
		||||
 | 
			
		||||
        midiBuffer.ensureSize (2048);
 | 
			
		||||
        midiBuffer.clear();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //==============================================================================
 | 
			
		||||
    Atomic<int> refCount { 1 };
 | 
			
		||||
 | 
			
		||||
    AudioProcessor* pluginInstance;
 | 
			
		||||
    ComSmartPtr<Vst::IHostApplication> host;
 | 
			
		||||
    ComSmartPtr<JuceAudioProcessor> comPluginInstance;
 | 
			
		||||
    ComSmartPtr<JuceVST3EditController> juceVST3EditController;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
        Since VST3 does not provide a way of knowing the buffer size and sample rate at any point,
 | 
			
		||||
        this object needs to be copied on every call to process() to be up-to-date...
 | 
			
		||||
    */
 | 
			
		||||
    Vst::ProcessContext processContext;
 | 
			
		||||
 | 
			
		||||
    Vst::ProcessSetup processSetup;
 | 
			
		||||
 | 
			
		||||
    MidiBuffer midiBuffer;
 | 
			
		||||
    Array<float*> channelListFloat;
 | 
			
		||||
    Array<double*> channelListDouble;
 | 
			
		||||
 | 
			
		||||
    AudioBuffer<float>  emptyBufferFloat;
 | 
			
		||||
    AudioBuffer<double> emptyBufferDouble;
 | 
			
		||||
 | 
			
		||||
   #if JucePlugin_WantsMidiInput
 | 
			
		||||
    bool isMidiInputBusEnabled = true;
 | 
			
		||||
   #else
 | 
			
		||||
    bool isMidiInputBusEnabled = false;
 | 
			
		||||
   #endif
 | 
			
		||||
 | 
			
		||||
   #if JucePlugin_ProducesMidiOutput
 | 
			
		||||
    bool isMidiOutputBusEnabled = true;
 | 
			
		||||
   #else
 | 
			
		||||
    bool isMidiOutputBusEnabled = false;
 | 
			
		||||
   #endif
 | 
			
		||||
 | 
			
		||||
    ScopedJuceInitialiser_GUI libraryInitialiser;
 | 
			
		||||
    static const char* kJucePrivateDataIdentifier;
 | 
			
		||||
 | 
			
		||||
    Array<const AudioProcessorParameterGroup*> parameterGroups;
 | 
			
		||||
 | 
			
		||||
    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (JuceVST3Component)
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -2531,7 +2739,7 @@ bool shutdownModule()
 | 
			
		||||
 | 
			
		||||
//==============================================================================
 | 
			
		||||
/** This typedef represents VST3's createInstance() function signature */
 | 
			
		||||
typedef FUnknown* (*CreateFunction) (Vst::IHostApplication*);
 | 
			
		||||
using CreateFunction = FUnknown* (*)(Vst::IHostApplication*);
 | 
			
		||||
 | 
			
		||||
static FUnknown* createComponentInstance (Vst::IHostApplication* host)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
@ -35,7 +35,7 @@
 | 
			
		||||
 | 
			
		||||
  ID:               juce_audio_plugin_client
 | 
			
		||||
  vendor:           juce
 | 
			
		||||
  version:          5.3.2
 | 
			
		||||
  version:          5.4.3
 | 
			
		||||
  name:             JUCE audio plugin wrapper classes
 | 
			
		||||
  description:      Classes for building VST, VST3, AudioUnit, AAX and RTAS plugins.
 | 
			
		||||
  website:          http://www.juce.com/juce
 | 
			
		||||
@ -54,6 +54,17 @@
 | 
			
		||||
#include <juce_audio_basics/juce_audio_basics.h>
 | 
			
		||||
#include <juce_audio_processors/juce_audio_processors.h>
 | 
			
		||||
 | 
			
		||||
/** Config: JUCE_VST3_CAN_REPLACE_VST2
 | 
			
		||||
 | 
			
		||||
    Enable this if you want your VST3 plug-in to load and save VST2 compatible
 | 
			
		||||
    state. This allows hosts to replace VST2 plug-ins with VST3 plug-ins. If
 | 
			
		||||
    you change this option then your VST3 plug-in will be incompatible with
 | 
			
		||||
    previous versions.
 | 
			
		||||
*/
 | 
			
		||||
#ifndef JUCE_VST3_CAN_REPLACE_VST2
 | 
			
		||||
 #define JUCE_VST3_CAN_REPLACE_VST2 1
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/** Config: JUCE_FORCE_USE_LEGACY_PARAM_IDS
 | 
			
		||||
 | 
			
		||||
    Enable this if you want to force JUCE to use a continuous parameter
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,27 @@
 | 
			
		||||
/*
 | 
			
		||||
  ==============================================================================
 | 
			
		||||
 | 
			
		||||
   This file is part of the JUCE library.
 | 
			
		||||
   Copyright (c) 2017 - ROLI Ltd.
 | 
			
		||||
 | 
			
		||||
   JUCE is an open source library subject to commercial or open-source
 | 
			
		||||
   licensing.
 | 
			
		||||
 | 
			
		||||
   By using JUCE, you agree to the terms of both the JUCE 5 End-User License
 | 
			
		||||
   Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
 | 
			
		||||
   27th April 2017).
 | 
			
		||||
 | 
			
		||||
   End User License Agreement: www.juce.com/juce-5-licence
 | 
			
		||||
   Privacy Policy: www.juce.com/juce-5-privacy-policy
 | 
			
		||||
 | 
			
		||||
   Or: You may also use this code under the terms of the GPL v3 (see
 | 
			
		||||
   www.gnu.org/licenses).
 | 
			
		||||
 | 
			
		||||
   JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
 | 
			
		||||
   EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
 | 
			
		||||
   DISCLAIMED.
 | 
			
		||||
 | 
			
		||||
  ==============================================================================
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "Unity/juce_Unity_Wrapper.cpp"
 | 
			
		||||
@ -30,7 +30,8 @@
 | 
			
		||||
#if ! (JucePlugin_Build_VST || JucePlugin_Build_VST3 \
 | 
			
		||||
        || JucePlugin_Build_AU || JucePlugin_Build_AUv3 \
 | 
			
		||||
        ||JucePlugin_Build_RTAS || JucePlugin_Build_AAX \
 | 
			
		||||
        || JucePlugin_Build_Standalone || JucePlugin_Build_LV2)
 | 
			
		||||
        || JucePlugin_Build_Standalone || JucePlugin_Build_LV2 \
 | 
			
		||||
        || JucePlugin_Build_Unity)
 | 
			
		||||
 #error "You need to enable at least one plugin format!"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@ -91,30 +92,3 @@
 | 
			
		||||
 #undef JucePlugin_Build_AAX
 | 
			
		||||
 #define JucePlugin_Build_AAX 0
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//==============================================================================
 | 
			
		||||
#if JucePlugin_Build_VST
 | 
			
		||||
 | 
			
		||||
 #if JucePlugin_VersionCode < 0x010000   // Major < 0
 | 
			
		||||
 | 
			
		||||
  #if (JucePlugin_VersionCode & 0x00FF00) > (9 * 0x100) // check if Minor number exceeeds 9
 | 
			
		||||
   #warning When version has "major" = 0, VST2 has trouble displaying "minor" exceeding 9
 | 
			
		||||
  #endif
 | 
			
		||||
 | 
			
		||||
  #if (JucePlugin_VersionCode & 0xFF) > 9   // check if Bugfix number exceeeds 9
 | 
			
		||||
   #warning When version has "major" = 0, VST2 has trouble displaying "bugfix" exceeding 9
 | 
			
		||||
  #endif
 | 
			
		||||
 | 
			
		||||
 #elif JucePlugin_VersionCode >= 0x650000   // Major >= 101
 | 
			
		||||
 | 
			
		||||
  #if (JucePlugin_VersionCode & 0x00FF00) > (99 * 0x100) // check if Minor number exceeeds 99
 | 
			
		||||
   #warning When version has "major" > 100, VST2 has trouble displaying "minor" exceeding 99
 | 
			
		||||
  #endif
 | 
			
		||||
 | 
			
		||||
  #if (JucePlugin_VersionCode & 0xFF) > 99  // check if Bugfix number exceeeds 99
 | 
			
		||||
   #warning When version has "major" > 100, VST2 has trouble displaying "bugfix" exceeding 99
 | 
			
		||||
  #endif
 | 
			
		||||
 | 
			
		||||
 #endif // JucePlugin_VersionCode
 | 
			
		||||
 | 
			
		||||
#endif // JucePlugin_Build_VST
 | 
			
		||||
 | 
			
		||||
@ -41,8 +41,8 @@ class PluginHostType
 | 
			
		||||
public:
 | 
			
		||||
    //==============================================================================
 | 
			
		||||
    PluginHostType()  : type (getHostType()) {}
 | 
			
		||||
    PluginHostType (const PluginHostType& other) noexcept  : type (other.type) {}
 | 
			
		||||
    PluginHostType& operator= (const PluginHostType& other) noexcept { type = other.type; return *this; }
 | 
			
		||||
    PluginHostType (const PluginHostType& other) = default;
 | 
			
		||||
    PluginHostType& operator= (const PluginHostType& other) = default;
 | 
			
		||||
 | 
			
		||||
    //==============================================================================
 | 
			
		||||
    /** Represents the host type and also its version for some hosts. */
 | 
			
		||||
@ -63,11 +63,14 @@ public:
 | 
			
		||||
        BitwigStudio,               /**< Represents Bitwig Studio. */
 | 
			
		||||
        CakewalkSonar8,             /**< Represents Cakewalk Sonar 8. */
 | 
			
		||||
        CakewalkSonarGeneric,       /**< Represents Cakewalk Sonar. */
 | 
			
		||||
        CakewalkByBandlab,          /**< Represents Cakewalk by Bandlab. */
 | 
			
		||||
        DaVinciResolve,             /**< Represents DaVinci Resolve. */
 | 
			
		||||
        DigitalPerformer,           /**< Represents Digital Performer. */
 | 
			
		||||
        FinalCut,                   /**< Represents Apple Final Cut Pro. */
 | 
			
		||||
        FruityLoops,                /**< Represents Fruity Loops. */
 | 
			
		||||
        JUCEPluginHost,             /**< Represents the JUCE AudioPluginHost */
 | 
			
		||||
        MagixSamplitude,            /**< Represents Magix Samplitude. */
 | 
			
		||||
        MagixSequoia,               /**< Represents Magix Sequoia. */
 | 
			
		||||
        MergingPyramix,             /**< Represents Merging Pyramix. */
 | 
			
		||||
        MuseReceptorGeneric,        /**< Represents Muse Receptor. */
 | 
			
		||||
        Reaper,                     /**< Represents Cockos Reaper. */
 | 
			
		||||
@ -81,6 +84,8 @@ public:
 | 
			
		||||
        SteinbergCubase8,           /**< Represents Steinberg Cubase 8. */
 | 
			
		||||
        SteinbergCubase8_5,         /**< Represents Steinberg Cubase 8.5. */
 | 
			
		||||
        SteinbergCubase9,           /**< Represents Steinberg Cubase 9. */
 | 
			
		||||
        SteinbergCubase9_5,         /**< Represents Steinberg Cubase 9.5. */
 | 
			
		||||
        SteinbergCubase10,          /**< Represents Steinberg Cubase 10. */
 | 
			
		||||
        SteinbergCubaseGeneric,     /**< Represents Steinberg Cubase. */
 | 
			
		||||
        SteinbergNuendo3,           /**< Represents Steinberg Nuendo 3. */
 | 
			
		||||
        SteinbergNuendo4,           /**< Represents Steinberg Nuendo 4. */
 | 
			
		||||
@ -112,7 +117,7 @@ public:
 | 
			
		||||
    /** Returns true if the host is Bitwig Studio. */
 | 
			
		||||
    bool isBitwigStudio() const noexcept      { return type == BitwigStudio; }
 | 
			
		||||
    /** Returns true if the host is any version of Steinberg Cubase. */
 | 
			
		||||
    bool isCubase() const noexcept            { return type == SteinbergCubase4 || type == SteinbergCubase5 || type == SteinbergCubase5Bridged || type == SteinbergCubase6 || type == SteinbergCubase7 || type == SteinbergCubase8 || type == SteinbergCubase8_5 || type == SteinbergCubase9 || type == SteinbergCubaseGeneric; }
 | 
			
		||||
    bool isCubase() const noexcept            { return type == SteinbergCubase4 || type == SteinbergCubase5 || type == SteinbergCubase5Bridged || type == SteinbergCubase6 || type == SteinbergCubase7 || type == SteinbergCubase8 || type == SteinbergCubase8_5 || type == SteinbergCubase9 || type == SteinbergCubase9_5 || type == SteinbergCubase10 || type == SteinbergCubaseGeneric; }
 | 
			
		||||
    /** Returns true if the host is Steinberg Cubase 7 or later. */
 | 
			
		||||
    bool isCubase7orLater() const noexcept    { return isCubase() && ! (type == SteinbergCubase4 || type == SteinbergCubase5 || type == SteinbergCubase6); }
 | 
			
		||||
    /** Returns true if the host is Steinberg Cubase 5 Bridged. */
 | 
			
		||||
@ -127,6 +132,8 @@ public:
 | 
			
		||||
    bool isFruityLoops() const noexcept       { return type == FruityLoops; }
 | 
			
		||||
    /** Returns true if the host is Apple GarageBand. */
 | 
			
		||||
    bool isGarageBand() const noexcept        { return type == AppleGarageBand; }
 | 
			
		||||
    /** Returns true if the host is the JUCE AudioPluginHost */
 | 
			
		||||
    bool isJUCEPluginHost() const noexcept    { return type == JUCEPluginHost; }
 | 
			
		||||
    /** Returns true if the host is Apple Logic Pro. */
 | 
			
		||||
    bool isLogic() const noexcept             { return type == AppleLogic; }
 | 
			
		||||
    /** Returns true if the host is Apple MainStage. */
 | 
			
		||||
@ -149,8 +156,10 @@ public:
 | 
			
		||||
    bool isSADiE() const noexcept             { return type == SADiE; }
 | 
			
		||||
    /** Returns true if the host is Magix Samplitude. */
 | 
			
		||||
    bool isSamplitude() const noexcept        { return type == MagixSamplitude; }
 | 
			
		||||
    /** Returns true if the host is Magix Sequoia. */
 | 
			
		||||
    bool isSequoia() const noexcept           { return type == MagixSequoia; }
 | 
			
		||||
    /** Returns true if the host is any version of Cakewalk Sonar. */
 | 
			
		||||
    bool isSonar() const noexcept             { return type == CakewalkSonar8 || type == CakewalkSonarGeneric; }
 | 
			
		||||
    bool isSonar() const noexcept             { return type == CakewalkSonar8 || type == CakewalkSonarGeneric || type == CakewalkByBandlab; }
 | 
			
		||||
    /** Returns true if the host is Steinberg's VST3 Test Host. */
 | 
			
		||||
    bool isSteinbergTestHost() const noexcept { return type == SteinbergTestHost; }
 | 
			
		||||
    /** Returns true if the host is any product from Steinberg. */
 | 
			
		||||
@ -190,11 +199,14 @@ public:
 | 
			
		||||
            case BitwigStudio:             return "Bitwig Studio";
 | 
			
		||||
            case CakewalkSonar8:           return "Cakewalk Sonar 8";
 | 
			
		||||
            case CakewalkSonarGeneric:     return "Cakewalk Sonar";
 | 
			
		||||
            case CakewalkByBandlab:        return "Cakewalk by Bandlab";
 | 
			
		||||
            case DaVinciResolve:           return "DaVinci Resolve";
 | 
			
		||||
            case DigitalPerformer:         return "DigitalPerformer";
 | 
			
		||||
            case FinalCut:                 return "Final Cut";
 | 
			
		||||
            case FruityLoops:              return "FruityLoops";
 | 
			
		||||
            case JUCEPluginHost:           return "JUCE AudioPluginHost";
 | 
			
		||||
            case MagixSamplitude:          return "Magix Samplitude";
 | 
			
		||||
            case MagixSequoia:             return "Magix Sequoia";
 | 
			
		||||
            case MergingPyramix:           return "Pyramix";
 | 
			
		||||
            case MuseReceptorGeneric:      return "Muse Receptor";
 | 
			
		||||
            case Reaper:                   return "Reaper";
 | 
			
		||||
@ -208,6 +220,8 @@ public:
 | 
			
		||||
            case SteinbergCubase8:         return "Steinberg Cubase 8";
 | 
			
		||||
            case SteinbergCubase8_5:       return "Steinberg Cubase 8.5";
 | 
			
		||||
            case SteinbergCubase9:         return "Steinberg Cubase 9";
 | 
			
		||||
            case SteinbergCubase9_5:       return "Steinberg Cubase 9.5";
 | 
			
		||||
            case SteinbergCubase10:        return "Steinberg Cubase 10";
 | 
			
		||||
            case SteinbergCubaseGeneric:   return "Steinberg Cubase";
 | 
			
		||||
            case SteinbergNuendo3:         return "Steinberg Nuendo 3";
 | 
			
		||||
            case SteinbergNuendo4:         return "Steinberg Nuendo 4";
 | 
			
		||||
@ -259,11 +273,15 @@ public:
 | 
			
		||||
    */
 | 
			
		||||
    static AudioProcessor::WrapperType getPluginLoadedAs() noexcept    { return jucePlugInClientCurrentWrapperType; }
 | 
			
		||||
 | 
			
		||||
    /** Returns true if the AudioProcessor instance is an AAX plug-in running in AudioSuite. */
 | 
			
		||||
    static bool isInAAXAudioSuite (AudioProcessor&);
 | 
			
		||||
 | 
			
		||||
    //==============================================================================
 | 
			
		||||
 | 
			
		||||
   #ifndef DOXYGEN
 | 
			
		||||
    // @internal
 | 
			
		||||
    static AudioProcessor::WrapperType jucePlugInClientCurrentWrapperType;
 | 
			
		||||
    static std::function<bool(AudioProcessor&)> jucePlugInIsRunningInAudioSuiteFn;
 | 
			
		||||
   #endif
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
@ -295,6 +313,8 @@ private:
 | 
			
		||||
        if (hostPath.containsIgnoreCase       ("Cubase 8.app"))      return SteinbergCubase8;
 | 
			
		||||
        if (hostPath.containsIgnoreCase       ("Cubase 8.5.app"))    return SteinbergCubase8_5;
 | 
			
		||||
        if (hostPath.containsIgnoreCase       ("Cubase 9.app"))      return SteinbergCubase9;
 | 
			
		||||
        if (hostPath.containsIgnoreCase       ("Cubase 9.5.app"))    return SteinbergCubase9_5;
 | 
			
		||||
        if (hostPath.containsIgnoreCase       ("Cubase 10.app"))     return SteinbergCubase10;
 | 
			
		||||
        if (hostFilename.containsIgnoreCase   ("Cubase"))            return SteinbergCubaseGeneric;
 | 
			
		||||
        if (hostPath.containsIgnoreCase       ("Wavelab 7"))         return SteinbergWavelab7;
 | 
			
		||||
        if (hostPath.containsIgnoreCase       ("Wavelab 8"))         return SteinbergWavelab8;
 | 
			
		||||
@ -309,6 +329,8 @@ private:
 | 
			
		||||
        if (hostFilename.containsIgnoreCase   ("Renoise"))           return Renoise;
 | 
			
		||||
        if (hostFilename.containsIgnoreCase   ("Resolve"))           return DaVinciResolve;
 | 
			
		||||
        if (hostFilename.startsWith           ("Bitwig"))            return BitwigStudio;
 | 
			
		||||
        if (hostFilename.containsIgnoreCase   ("OsxFL"))             return FruityLoops;
 | 
			
		||||
        if (hostFilename.containsIgnoreCase   ("AudioPluginHost"))   return JUCEPluginHost;
 | 
			
		||||
 | 
			
		||||
       #elif JUCE_WINDOWS
 | 
			
		||||
        if (hostFilename.containsIgnoreCase   ("Live 6."))           return AbletonLive6;
 | 
			
		||||
@ -320,6 +342,7 @@ private:
 | 
			
		||||
        if (hostFilename.containsIgnoreCase   ("ProTools"))          return AvidProTools;
 | 
			
		||||
        if (hostPath.containsIgnoreCase       ("SONAR 8"))           return CakewalkSonar8;
 | 
			
		||||
        if (hostFilename.containsIgnoreCase   ("SONAR"))             return CakewalkSonarGeneric;
 | 
			
		||||
        if (hostFilename.containsIgnoreCase   ("Cakewalk.exe"))      return CakewalkByBandlab;
 | 
			
		||||
        if (hostFilename.containsIgnoreCase   ("GarageBand"))        return AppleGarageBand;
 | 
			
		||||
        if (hostFilename.containsIgnoreCase   ("Logic"))             return AppleLogic;
 | 
			
		||||
        if (hostFilename.containsIgnoreCase   ("MainStage"))         return AppleMainStage;
 | 
			
		||||
@ -333,9 +356,13 @@ private:
 | 
			
		||||
        if (hostFilename.containsIgnoreCase   ("Cubase7"))           return SteinbergCubase7;
 | 
			
		||||
        if (hostFilename.containsIgnoreCase   ("Cubase8.exe"))       return SteinbergCubase8;
 | 
			
		||||
        if (hostFilename.containsIgnoreCase   ("Cubase8.5.exe"))     return SteinbergCubase8_5;
 | 
			
		||||
        // Cubase 9 scans plug-ins with a separate executable "vst2xscanner"
 | 
			
		||||
        // Later version of Cubase scan plug-ins with a separate executable "vst2xscanner"
 | 
			
		||||
        if (hostFilename.containsIgnoreCase   ("Cubase9.5.exe")
 | 
			
		||||
            || hostPath.containsIgnoreCase    ("Cubase 9.5"))        return SteinbergCubase9_5;
 | 
			
		||||
        if (hostFilename.containsIgnoreCase   ("Cubase9.exe")
 | 
			
		||||
            || hostPath.containsIgnoreCase    ("Cubase 9"))          return SteinbergCubase9;
 | 
			
		||||
        if (hostFilename.containsIgnoreCase   ("Cubase10.exe")
 | 
			
		||||
            || hostPath.containsIgnoreCase    ("Cubase 10"))         return SteinbergCubase10;
 | 
			
		||||
        if (hostFilename.containsIgnoreCase   ("Cubase"))            return SteinbergCubaseGeneric;
 | 
			
		||||
        if (hostFilename.containsIgnoreCase   ("VSTBridgeApp"))      return SteinbergCubase5Bridged;
 | 
			
		||||
        if (hostPath.containsIgnoreCase       ("Wavelab 5"))         return SteinbergWavelab5;
 | 
			
		||||
@ -353,16 +380,19 @@ private:
 | 
			
		||||
        if (hostFilename.containsIgnoreCase   ("VST_Scanner"))       return VBVSTScanner;
 | 
			
		||||
        if (hostPath.containsIgnoreCase       ("Merging Technologies")) return MergingPyramix;
 | 
			
		||||
        if (hostFilename.startsWithIgnoreCase ("Sam"))               return MagixSamplitude;
 | 
			
		||||
        if (hostFilename.startsWithIgnoreCase ("Sequoia"))           return MagixSequoia;
 | 
			
		||||
        if (hostFilename.containsIgnoreCase   ("Renoise"))           return Renoise;
 | 
			
		||||
        if (hostFilename.containsIgnoreCase   ("Resolve"))           return DaVinciResolve;
 | 
			
		||||
        if (hostPath.containsIgnoreCase       ("Bitwig Studio"))     return BitwigStudio;
 | 
			
		||||
        if (hostFilename.containsIgnoreCase   ("Sadie"))             return SADiE;
 | 
			
		||||
        if (hostFilename.containsIgnoreCase   ("AudioPluginHost"))   return JUCEPluginHost;
 | 
			
		||||
 | 
			
		||||
       #elif JUCE_LINUX
 | 
			
		||||
        if (hostFilename.containsIgnoreCase   ("Ardour"))            return Ardour;
 | 
			
		||||
        if (hostFilename.startsWithIgnoreCase ("Waveform"))          return TracktionWaveform;
 | 
			
		||||
        if (hostFilename.containsIgnoreCase   ("Tracktion"))         return TracktionGeneric;
 | 
			
		||||
        if (hostFilename.startsWith           ("Bitwig"))            return BitwigStudio;
 | 
			
		||||
        if (hostFilename.containsIgnoreCase   ("AudioPluginHost"))   return JUCEPluginHost;
 | 
			
		||||
 | 
			
		||||
       #elif JUCE_IOS
 | 
			
		||||
       #elif JUCE_ANDROID
 | 
			
		||||
 | 
			
		||||
@ -38,6 +38,23 @@ namespace juce
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
AudioProcessor::WrapperType PluginHostType::jucePlugInClientCurrentWrapperType = AudioProcessor::wrapperType_Undefined;
 | 
			
		||||
std::function<bool(AudioProcessor&)> PluginHostType::jucePlugInIsRunningInAudioSuiteFn = nullptr;
 | 
			
		||||
 | 
			
		||||
#if JucePlugin_Build_Unity
 | 
			
		||||
 bool juce_isRunningInUnity()    { return PluginHostType::getPluginLoadedAs() == AudioProcessor::wrapperType_Unity; }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if JUCE_MODULE_AVAILABLE_juce_opengl
 | 
			
		||||
 bool juce_shouldDoubleScaleNativeGLWindow()
 | 
			
		||||
 {
 | 
			
		||||
     auto wrapperType = PluginHostType::getPluginLoadedAs();
 | 
			
		||||
 | 
			
		||||
     if (wrapperType == AudioProcessor::wrapperType_VST || wrapperType == AudioProcessor::wrapperType_VST3)
 | 
			
		||||
         return getHostType().type == PluginHostType::SteinbergCubase10;
 | 
			
		||||
 | 
			
		||||
     return false;
 | 
			
		||||
 }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef JUCE_VST3_CAN_REPLACE_VST2
 | 
			
		||||
 #define JUCE_VST3_CAN_REPLACE_VST2 1
 | 
			
		||||
@ -151,12 +168,12 @@ bool JUCE_API handleManufacturerSpecificVST2Opcode (int32 index, pointer_sized_i
 | 
			
		||||
extern AudioProcessor* JUCE_CALLTYPE createPluginFilter();
 | 
			
		||||
 | 
			
		||||
#if JucePlugin_Enable_IAA && JucePlugin_Build_Standalone && JUCE_IOS && (! JUCE_USE_CUSTOM_PLUGIN_STANDALONE_APP)
 | 
			
		||||
extern bool JUCE_CALLTYPE juce_isInterAppAudioConnected();
 | 
			
		||||
extern void JUCE_CALLTYPE juce_switchToHostApplication();
 | 
			
		||||
 extern bool JUCE_CALLTYPE juce_isInterAppAudioConnected();
 | 
			
		||||
 extern void JUCE_CALLTYPE juce_switchToHostApplication();
 | 
			
		||||
 | 
			
		||||
#if JUCE_MODULE_AVAILABLE_juce_gui_basics
 | 
			
		||||
extern Image JUCE_CALLTYPE juce_getIAAHostIcon (int);
 | 
			
		||||
#endif
 | 
			
		||||
 #if JUCE_MODULE_AVAILABLE_juce_gui_basics
 | 
			
		||||
 extern Image JUCE_CALLTYPE juce_getIAAHostIcon (int);
 | 
			
		||||
 #endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
AudioProcessor* JUCE_API JUCE_CALLTYPE createPluginFilterOfType (AudioProcessor::WrapperType type)
 | 
			
		||||
@ -189,6 +206,20 @@ void PluginHostType::switchToHostApplication() const
 | 
			
		||||
   #endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool PluginHostType::isInAAXAudioSuite (AudioProcessor& processor)
 | 
			
		||||
{
 | 
			
		||||
   #if JucePlugin_Build_AAX
 | 
			
		||||
    if (PluginHostType::getPluginLoadedAs() == AudioProcessor::wrapperType_AAX
 | 
			
		||||
        && jucePlugInIsRunningInAudioSuiteFn != nullptr)
 | 
			
		||||
    {
 | 
			
		||||
        return jucePlugInIsRunningInAudioSuiteFn (processor);
 | 
			
		||||
    }
 | 
			
		||||
   #endif
 | 
			
		||||
 | 
			
		||||
    ignoreUnused (processor);
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if JUCE_MODULE_AVAILABLE_juce_gui_basics
 | 
			
		||||
namespace juce {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user