text:
/*
  ==============================================================================

   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.

  ==============================================================================
*/

namespace juce
{

//==============================================================================
/**
    This maintains a list of known AudioPluginFormats.

    @see AudioPluginFormat
*/
class JUCE_API  AudioPluginFormatManager
{
public:
    //==============================================================================
    AudioPluginFormatManager();

    /** Destructor. */
    ~AudioPluginFormatManager();

    //==============================================================================
    /** Adds any formats that it knows about, e.g. VST.
    */
    void addDefaultFormats();

    //==============================================================================
    /** Returns the number of types of format that are available.

        Use getFormat() to get one of them.
    */
    int getNumFormats();

    /** Returns one of the available formats.

        @see getNumFormats
    */
    AudioPluginFormat* getFormat (int index);

    //==============================================================================
    /** Adds a format to the list.

        The object passed in will be owned and deleted by the manager.
    */
    void addFormat (AudioPluginFormat* format);

    //==============================================================================
    /** Tries to load the type for this description, by trying all the formats
        that this manager knows about.

        The caller is responsible for deleting the object that is returned.

        If it can't load the plugin, it returns nullptr and leaves a message in the
        errorMessage string.

        If you intend to instantiate a AudioUnit v3 plug-in then you must either
        use the non-blocking asynchrous version below - or call this method from a
        thread other than the message thread and without blocking the message
        thread.
    */
    AudioPluginInstance* createPluginInstance (const PluginDescription& description,
                                               double initialSampleRate,
                                               int initialBufferSize,
                                               String& errorMessage) const;

    /** Tries to asynchronously load the type for this description, by trying
        all the formats that this manager knows about.

        The caller must supply a callback object which will be called when
        the instantantiation has completed.

        If it can't load the plugin then the callback function will be called
        passing a nullptr as the instance argument along with an error message.

        The callback function will be called on the message thread so the caller
        must not block the message thread.

        The callback object will be deleted automatically after it has been
        invoked.

        The caller is responsible for deleting the instance that is passed to
        the callback function.

        If you intend to instantiate a AudioUnit v3 plug-in then you must use
        this non-blocking asynchrous version - or call the synchrous method
        from an auxiliary thread.
    */
    void createPluginInstanceAsync (const PluginDescription& description,
                                    double initialSampleRate,
                                    int initialBufferSize,
                                    AudioPluginFormat::InstantiationCompletionCallback* callback);

    void createPluginInstanceAsync (const PluginDescription& description,
                                    double initialSampleRate,
                                    int initialBufferSize,
                                    std::function<void (AudioPluginInstance*, const String&)> completionCallback);

    /** Checks that the file or component for this plugin actually still exists.

        (This won't try to load the plugin)
    */
    bool doesPluginStillExist (const PluginDescription& description) const;

private:
    //==============================================================================
    //@internal
    AudioPluginFormat* findFormatForDescription (const PluginDescription&, String& errorMessage) const;

    OwnedArray<AudioPluginFormat> formats;

    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioPluginFormatManager)
};

} // namespace juce


text:
/*
  ==============================================================================

   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.

  ==============================================================================
*/

namespace juce
{

namespace AudioPluginFormatHelpers
{
    struct CallbackInvoker
    {
        struct InvokeOnMessageThread : public CallbackMessage
        {
            InvokeOnMessageThread (AudioPluginInstance* inInstance, const String& inError,
                                   AudioPluginFormat::InstantiationCompletionCallback* inCompletion,
                                   CallbackInvoker* invoker)
                : instance (inInstance), error (inError), compCallback (inCompletion), owner (invoker)
            {}

            void messageCallback() override     { compCallback->completionCallback (instance, error); }

            //==============================================================================
            AudioPluginInstance* instance;
            String error;
            ScopedPointer<AudioPluginFormat::InstantiationCompletionCallback> compCallback;
            ScopedPointer<CallbackInvoker> owner;
        };

        //==============================================================================
        CallbackInvoker (AudioPluginFormat::InstantiationCompletionCallback* cc)  : completion (cc)
        {}

        void completionCallback (AudioPluginInstance* instance, const String& error)
        {
            (new InvokeOnMessageThread (instance, error, completion, this))->post();
        }

        static void staticCompletionCallback (void* userData, AudioPluginInstance* instance, const String& error)
        {
            reinterpret_cast<CallbackInvoker*> (userData)->completionCallback (instance, error);
        }

        //==============================================================================
        AudioPluginFormat::InstantiationCompletionCallback* completion;
    };
}

AudioPluginFormat::AudioPluginFormat() noexcept {}
AudioPluginFormat::~AudioPluginFormat() {}

AudioPluginInstance* AudioPluginFormat::createInstanceFromDescription (const PluginDescription& desc,
                                                                       double initialSampleRate,
                                                                       int initialBufferSize)
{
    String errorMessage;
    return createInstanceFromDescription (desc, initialSampleRate, initialBufferSize, errorMessage);
}

//==============================================================================
struct EventSignaler : public AudioPluginFormat::InstantiationCompletionCallback
{
    EventSignaler (WaitableEvent& inEvent, AudioPluginInstance*& inInstance, String& inErrorMessage)
        : event (inEvent), outInstance (inInstance), outErrorMessage (inErrorMessage)
    {}

    void completionCallback (AudioPluginInstance* newInstance, const String& result) override
    {
        outInstance = newInstance;
        outErrorMessage = result;
        event.signal();
    }

    static void staticCompletionCallback (void* userData, AudioPluginInstance* pluginInstance, const String& error)
    {
        reinterpret_cast<EventSignaler*> (userData)->completionCallback (pluginInstance, error);
    }

    WaitableEvent& event;
    AudioPluginInstance*& outInstance;
    String& outErrorMessage;

    JUCE_DECLARE_NON_COPYABLE (EventSignaler)
};

AudioPluginInstance* AudioPluginFormat::createInstanceFromDescription (const PluginDescription& desc,
                                                                       double initialSampleRate,
                                                                       int initialBufferSize,
                                                                       String& errorMessage)
{
    if (MessageManager::getInstance()->isThisTheMessageThread()
          && requiresUnblockedMessageThreadDuringCreation(desc))
    {
        errorMessage = NEEDS_TRANS ("This plug-in cannot be instantiated synchronously");
        return nullptr;
    }

    WaitableEvent waitForCreation;
    AudioPluginInstance* instance = nullptr;

    ScopedPointer<EventSignaler> eventSignaler (new EventSignaler (waitForCreation, instance, errorMessage));

    if (! MessageManager::getInstance()->isThisTheMessageThread())
        createPluginInstanceAsync (desc, initialSampleRate, initialBufferSize, eventSignaler.release());
    else
        createPluginInstance (desc, initialSampleRate, initialBufferSize,
                              eventSignaler, EventSignaler::staticCompletionCallback);

    waitForCreation.wait();

    return instance;
}

void AudioPluginFormat::createPluginInstanceAsync (const PluginDescription& description,
                                                   double initialSampleRate,
                                                   int initialBufferSize,
                                                   AudioPluginFormat::InstantiationCompletionCallback* callback)
{
    if (MessageManager::getInstance()->isThisTheMessageThread())
    {
        createPluginInstanceOnMessageThread (description, initialSampleRate, initialBufferSize, callback);
        return;
    }

    //==============================================================================
    struct InvokeOnMessageThread  : public CallbackMessage
    {
        InvokeOnMessageThread (AudioPluginFormat* myself,
                               const PluginDescription& descriptionParam,
                               double initialSampleRateParam,
                               int initialBufferSizeParam,
                               AudioPluginFormat::InstantiationCompletionCallback* callbackParam)
            : owner (myself), descr (descriptionParam), sampleRate (initialSampleRateParam),
              bufferSize (initialBufferSizeParam), call (callbackParam)
        {}

        void messageCallback() override
        {
            owner->createPluginInstanceOnMessageThread (descr, sampleRate, bufferSize, call);
        }

        AudioPluginFormat* owner;
        PluginDescription descr;
        double sampleRate;
        int bufferSize;
        AudioPluginFormat::InstantiationCompletionCallback* call;
    };

    (new InvokeOnMessageThread (this, description, initialSampleRate, initialBufferSize, callback))->post();
}

void AudioPluginFormat::createPluginInstanceAsync (const PluginDescription& description,
                                                   double initialSampleRate,
                                                   int initialBufferSize,
                                                   std::function<void (AudioPluginInstance*, const String&)> f)
{
    struct CallbackInvoker  : public AudioPluginFormat::InstantiationCompletionCallback
    {
        CallbackInvoker (std::function<void (AudioPluginInstance*, const String&)> inCompletion)
            : completion (inCompletion)
        {}

        void completionCallback (AudioPluginInstance* instance, const String& error) override
        {
            completion (instance, error);
        }

        std::function<void (AudioPluginInstance*, const String&)> completion;
    };

    createPluginInstanceAsync (description, initialSampleRate, initialBufferSize, new CallbackInvoker (f));
}

void AudioPluginFormat::createPluginInstanceOnMessageThread (const PluginDescription& description,
                                                             double initialSampleRate,
                                                             int initialBufferSize,
                                                             AudioPluginFormat::InstantiationCompletionCallback* callback)
{
    jassert (callback != nullptr);
    jassert (MessageManager::getInstance()->isThisTheMessageThread());

    //==============================================================================

    //==============================================================================
    AudioPluginFormatHelpers::CallbackInvoker* completion = new AudioPluginFormatHelpers::CallbackInvoker (callback);

    createPluginInstance (description, initialSampleRate, initialBufferSize, completion,
                          AudioPluginFormatHelpers::CallbackInvoker::staticCompletionCallback);
}

} // namespace juce

repo_name: fedden/RenderMan

mime_type: text/x-c++


text:
/*
  ==============================================================================

   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.

  ==============================================================================
*/

namespace juce
{

namespace PluginFormatManagerHelpers
{
    struct ErrorCallbackOnMessageThread : public CallbackMessage
    {
        ErrorCallbackOnMessageThread (const String& inError,
                                      AudioPluginFormat::InstantiationCompletionCallback* inCallback)
            : error (inError), callback (inCallback)
        {
        }

        void messageCallback() override          { callback->completionCallback (nullptr, error); }

        String error;
        ScopedPointer<AudioPluginFormat::InstantiationCompletionCallback> callback;
    };

    struct ErrorLambdaOnMessageThread : public CallbackMessage
    {
        ErrorLambdaOnMessageThread (const String& inError,
                                    std::function<void (AudioPluginInstance*, const String&)> f)
            : error (inError), lambda (f)
        {
        }

        void messageCallback() override          { lambda (nullptr, error); }

        String error;
        std::function<void (AudioPluginInstance*, const String&)> lambda;
    };
}

AudioPluginFormatManager::AudioPluginFormatManager() {}
AudioPluginFormatManager::~AudioPluginFormatManager() {}

//==============================================================================
void AudioPluginFormatManager::addDefaultFormats()
{
   #if JUCE_DEBUG
    // you should only call this method once!
    for (int i = formats.size(); --i >= 0;)
    {
       #if JUCE_PLUGINHOST_VST && (JUCE_MAC || JUCE_WINDOWS || JUCE_LINUX || JUCE_IOS)
        jassert (dynamic_cast<VSTPluginFormat*> (formats[i]) == nullptr);
       #endif

       #if JUCE_PLUGINHOST_VST3 && (JUCE_MAC || JUCE_WINDOWS)
        jassert (dynamic_cast<VST3PluginFormat*> (formats[i]) == nullptr);
       #endif

       #if JUCE_PLUGINHOST_AU && (JUCE_MAC || JUCE_IOS)
        jassert (dynamic_cast<AudioUnitPluginFormat*> (formats[i]) == nullptr);
       #endif

       #if JUCE_PLUGINHOST_LADSPA && JUCE_LINUX
        jassert (dynamic_cast<LADSPAPluginFormat*> (formats[i]) == nullptr);
       #endif
    }
   #endif

   #if JUCE_PLUGINHOST_AU && (JUCE_MAC || JUCE_IOS)
    formats.add (new AudioUnitPluginFormat());
   #endif

   #if JUCE_PLUGINHOST_VST && (JUCE_MAC || JUCE_WINDOWS || JUCE_LINUX || JUCE_IOS)
    formats.add (new VSTPluginFormat());
   #endif

   #if JUCE_PLUGINHOST_VST3 && (JUCE_MAC || JUCE_WINDOWS)
    formats.add (new VST3PluginFormat());
   #endif

   #if JUCE_PLUGINHOST_LADSPA && JUCE_LINUX
    formats.add (new LADSPAPluginFormat());
   #endif
}

int AudioPluginFormatManager::getNumFormats()
{
    return formats.size();
}

AudioPluginFormat* AudioPluginFormatManager::getFormat (const int index)
{
    return formats [index];
}

void AudioPluginFormatManager::addFormat (AudioPluginFormat* const format)
{
    formats.add (format);
}

AudioPluginInstance* AudioPluginFormatManager::createPluginInstance (const PluginDescription& description, double rate,
                                                                     int blockSize, String& errorMessage) const
{
    if (AudioPluginFormat* format = findFormatForDescription (description, errorMessage))
        return format->createInstanceFromDescription (description, rate, blockSize, errorMessage);

    return nullptr;
}

void AudioPluginFormatManager::createPluginInstanceAsync (const PluginDescription& description,
                                                          double initialSampleRate,
                                                          int initialBufferSize,
                                                          AudioPluginFormat::InstantiationCompletionCallback* callback)
{
    String error;

    if (AudioPluginFormat* format = findFormatForDescription (description, error))
        return format->createPluginInstanceAsync (description, initialSampleRate, initialBufferSize, callback);

    (new PluginFormatManagerHelpers::ErrorCallbackOnMessageThread (error, callback))->post();
}

void AudioPluginFormatManager::createPluginInstanceAsync (const PluginDescription& description,
                                                          double initialSampleRate,
                                                          int initialBufferSize,
                                                          std::function<void (AudioPluginInstance*, const String&)> f)
{
    String error;

    if (AudioPluginFormat* format = findFormatForDescription (description, error))
        return format->createPluginInstanceAsync (description, initialSampleRate, initialBufferSize, f);

    (new PluginFormatManagerHelpers::ErrorLambdaOnMessageThread (error, f))->post();
}

AudioPluginFormat* AudioPluginFormatManager::findFormatForDescription (const PluginDescription& description, String& errorMessage) const
{
    errorMessage = String();

    for (int i = 0; i < formats.size(); ++i)
    {
        AudioPluginFormat* format;

        if ((format = formats.getUnchecked (i))->getName() == description.pluginFormatName
               && format->fileMightContainThisPluginType (description.fileOrIdentifier))
            return format;
    }

    errorMessage = NEEDS_TRANS ("No compatible plug-in format exists for this plug-in");

    return nullptr;
}

bool AudioPluginFormatManager::doesPluginStillExist (const PluginDescription& description) const
{
    for (int i = 0; i < formats.size(); ++i)
        if (formats.getUnchecked(i)->getName() == description.pluginFormatName)
            return formats.getUnchecked(i)->doesPluginStillExist (description);

    return false;
}

} // namespace juce


text:
/*
  ==============================================================================

   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.

  ==============================================================================
*/

namespace juce
{

//==============================================================================
/**
    The base class for a type of plugin format, such as VST, AudioUnit, LADSPA, etc.

    @see AudioPluginFormatManager
*/
class JUCE_API  AudioPluginFormat
{
public:
    //==============================================================================
    struct JUCE_API  InstantiationCompletionCallback
    {
        virtual ~InstantiationCompletionCallback() {}
        virtual void completionCallback (AudioPluginInstance* instance, const String& error) = 0;

        JUCE_LEAK_DETECTOR (InstantiationCompletionCallback)
    };

    //==============================================================================
    /** Destructor. */
    virtual ~AudioPluginFormat();

    //==============================================================================
    /** Returns the format name.
        E.g. "VST", "AudioUnit", etc.
    */
    virtual String getName() const = 0;

    /** This tries to create descriptions for all the plugin types available in
        a binary module file.

        The file will be some kind of DLL or bundle.

        Normally there will only be one type returned, but some plugins
        (e.g. VST shells) can use a single DLL to create a set of different plugin
        subtypes, so in that case, each subtype is returned as a separate object.
    */
    virtual void findAllTypesForFile (OwnedArray<PluginDescription>& results,
                                      const String& fileOrIdentifier) = 0;

    /** Tries to recreate a type from a previously generated PluginDescription.
        @see AudioPluginFormatManager::createInstance
    */
    AudioPluginInstance* createInstanceFromDescription (const PluginDescription&,
                                                        double initialSampleRate,
                                                        int initialBufferSize);

    /** Same as above but with the possibility of returning an error message.

        @see AudioPluginFormatManager::createInstance
    */
    AudioPluginInstance* createInstanceFromDescription (const PluginDescription&,
                                                        double initialSampleRate,
                                                        int initialBufferSize,
                                                        String& errorMessage);

    /** Tries to recreate a type from a previously generated PluginDescription.

        @see AudioPluginFormatManager::createInstanceAsync
     */
    void createPluginInstanceAsync (const PluginDescription& description,
                                    double initialSampleRate,
                                    int initialBufferSize,
                                    InstantiationCompletionCallback* completionCallback);

    void createPluginInstanceAsync (const PluginDescription& description,
                                    double initialSampleRate,
                                    int initialBufferSize,
                                    std::function<void (AudioPluginInstance*, const String&)> completionCallback);

    /** Should do a quick check to see if this file or directory might be a plugin of
        this format.

        This is for searching for potential files, so it shouldn't actually try to
        load the plugin or do anything time-consuming.
    */
    virtual bool fileMightContainThisPluginType (const String& fileOrIdentifier) = 0;

    /** Returns a readable version of the name of the plugin that this identifier refers to. */
    virtual String getNameOfPluginFromIdentifier (const String& fileOrIdentifier) = 0;

    /** Returns true if this plugin's version or date has changed and it should be re-checked. */
    virtual bool pluginNeedsRescanning (const PluginDescription&) = 0;

    /** Checks whether this plugin could possibly be loaded.
        It doesn't actually need to load it, just to check whether the file or component
        still exists.
    */
    virtual bool doesPluginStillExist (const PluginDescription&) = 0;

    /** Returns true if this format needs to run a scan to find its list of plugins. */
    virtual bool canScanForPlugins() const = 0;

    /** Searches a suggested set of directories for any plugins in this format.
        The path might be ignored, e.g. by AUs, which are found by the OS rather
        than manually.

        @param directoriesToSearch   This specifies which directories shall be
                                     searched for plug-ins.
        @param recursive             Should the search recursively traverse folders.
        @param allowPluginsWhichRequireAsynchronousInstantiation
                                     If this is false then plug-ins which require
                                     asynchronous creation will be excluded.
    */
    virtual StringArray searchPathsForPlugins (const FileSearchPath& directoriesToSearch,
                                               bool recursive,
                                               bool allowPluginsWhichRequireAsynchronousInstantiation = false) = 0;

    /** Returns the typical places to look for this kind of plugin.

        Note that if this returns no paths, it means that the format doesn't search in
        files or folders, e.g. AudioUnits.
    */
    virtual FileSearchPath getDefaultLocationsToSearch() = 0;

protected:
    //==============================================================================
    friend class AudioPluginFormatManager;

    AudioPluginFormat() noexcept;

    /** Implementors must override this function. This is guaranteed to be called on
        the message thread. You may call the callback on any thread.
    */
    virtual void createPluginInstance (const PluginDescription&, double initialSampleRate,
                                       int initialBufferSize, void* userData,
                                       void (*callback) (void*, AudioPluginInstance*, const String&)) = 0;

    virtual bool requiresUnblockedMessageThreadDuringCreation (const PluginDescription&) const noexcept = 0;

private:
    /** @internal */
    void createPluginInstanceOnMessageThread (const PluginDescription&, double rate, int size,
                                              AudioPluginFormat::InstantiationCompletionCallback*);

    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioPluginFormat)
};

} // namespace juce


text:
/*
  ==============================================================================

   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.

  ==============================================================================
*/

namespace juce
{

#if (JUCE_PLUGINHOST_LADSPA && JUCE_LINUX) || DOXYGEN

//==============================================================================
/**
    Implements a plugin format manager for LADSPA plugins.
*/
class JUCE_API  LADSPAPluginFormat   : public AudioPluginFormat
{
public:
    LADSPAPluginFormat();
    ~LADSPAPluginFormat();

    //==============================================================================
    String getName() const override                { return "LADSPA"; }
    void findAllTypesForFile (OwnedArray<PluginDescription>&, const String& fileOrIdentifier) override;
    bool fileMightContainThisPluginType (const String& fileOrIdentifier) override;
    String getNameOfPluginFromIdentifier (const String& fileOrIdentifier) override;
    bool pluginNeedsRescanning (const PluginDescription&) override;
    StringArray searchPathsForPlugins (const FileSearchPath&, bool recursive, bool) override;
    bool doesPluginStillExist (const PluginDescription&) override;
    FileSearchPath getDefaultLocationsToSearch() override;
    bool canScanForPlugins() const override        { return true; }

private:
    //==============================================================================
    void createPluginInstance (const PluginDescription&, double initialSampleRate,
                               int initialBufferSize, void* userData,
                               void (*callback) (void*, AudioPluginInstance*, const String&)) override;

    bool requiresUnblockedMessageThreadDuringCreation (const PluginDescription&) const noexcept override;

private:
    void recursiveFileSearch (StringArray&, const File&, bool recursive);

    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LADSPAPluginFormat)
};

#endif

}


text:
/*
  ==============================================================================

   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.

  ==============================================================================
*/

// This macro can be set if you need to override this internal name for some reason..
#ifndef JUCE_STATE_DICTIONARY_KEY
 #define JUCE_STATE_DICTIONARY_KEY   "jucePluginState"
#endif

namespace juce
{

struct AudioUnitHelpers
{
    class ChannelRemapper
    {
    public:
        ChannelRemapper (AudioProcessor& p) : processor (p), inputLayoutMap (nullptr), outputLayoutMap (nullptr) {}
        ~ChannelRemapper() {}

        void alloc()
        {
            const int numInputBuses  = AudioUnitHelpers::getBusCount (&processor, true);
            const int numOutputBuses = AudioUnitHelpers::getBusCount (&processor, false);

            initializeChannelMapArray (true, numInputBuses);
            initializeChannelMapArray (false, numOutputBuses);

            for (int busIdx = 0; busIdx < numInputBuses; ++busIdx)
                fillLayoutChannelMaps (true, busIdx);

            for (int busIdx = 0; busIdx < numOutputBuses; ++busIdx)
                fillLayoutChannelMaps (false, busIdx);
        }

        void release()
        {
            inputLayoutMap = outputLayoutMap = nullptr;
            inputLayoutMapPtrStorage.free();
            outputLayoutMapPtrStorage.free();
            inputLayoutMapStorage.free();
            outputLayoutMapStorage.free();
        }

        inline const int* get (bool input, int bus) const noexcept { return (input ? inputLayoutMap : outputLayoutMap) [bus]; }

    private:
        //==============================================================================
        AudioProcessor& processor;
        HeapBlock<int*> inputLayoutMapPtrStorage, outputLayoutMapPtrStorage;
        HeapBlock<int>  inputLayoutMapStorage, outputLayoutMapStorage;
        int** inputLayoutMap;
        int** outputLayoutMap;

        //==============================================================================
        void initializeChannelMapArray (bool isInput, const int numBuses)
        {
            HeapBlock<int*>& layoutMapPtrStorage = isInput ? inputLayoutMapPtrStorage : outputLayoutMapPtrStorage;
            HeapBlock<int>& layoutMapStorage = isInput ? inputLayoutMapStorage : outputLayoutMapStorage;
            int**& layoutMap = isInput ? inputLayoutMap : outputLayoutMap;

            const int totalInChannels  = processor.getTotalNumInputChannels();
            const int totalOutChannels = processor.getTotalNumOutputChannels();

            layoutMapPtrStorage.calloc (static_cast<size_t> (numBuses));
            layoutMapStorage.calloc (static_cast<size_t> (isInput ? totalInChannels : totalOutChannels));

            layoutMap  = layoutMapPtrStorage. get();

            int ch = 0;
            for (int busIdx = 0; busIdx < numBuses; ++busIdx)
            {
                layoutMap[busIdx] = layoutMapStorage.get() + ch;
                ch += processor.getChannelCountOfBus (isInput, busIdx);
            }
        }

        void fillLayoutChannelMaps (bool isInput, int busNr)
        {
            int* layoutMap = (isInput ? inputLayoutMap : outputLayoutMap)[busNr];
            auto channelFormat = processor.getChannelLayoutOfBus (isInput, busNr);
            AudioChannelLayout coreAudioLayout;

            zerostruct (coreAudioLayout);
            coreAudioLayout.mChannelLayoutTag = CoreAudioLayouts::toCoreAudio (channelFormat);

            const int numChannels = channelFormat.size();
            auto coreAudioChannels = CoreAudioLayouts::getCoreAudioLayoutChannels (coreAudioLayout);

            for (int i = 0; i < numChannels; ++i)
                layoutMap[i] = coreAudioChannels.indexOf (channelFormat.getTypeOfChannel (i));
        }
    };

    //==============================================================================
    class CoreAudioBufferList
    {
    public:
        CoreAudioBufferList() { reset(); }

        //==============================================================================
        void prepare (int inChannels, int outChannels, int maxFrames)
        {
            const int numChannels = jmax (inChannels, outChannels);

            scratch.setSize (numChannels, maxFrames);
            channels.calloc (static_cast<size_t> (numChannels));

            reset();
        }

        void release()
        {
            scratch.setSize (0, 0);
            channels.free();
        }

        void reset() noexcept
        {
            pushIdx = 0;
            popIdx = 0;
            zeromem (channels.get(), sizeof(float*) * static_cast<size_t> (scratch.getNumChannels()));
        }

        //==============================================================================
        float* setBuffer (const int idx, float* ptr = nullptr) noexcept
        {
            jassert (idx < scratch.getNumChannels());
            return (channels [idx] = uniqueBuffer (idx, ptr));
        }

        //==============================================================================
        float* push() noexcept
        {
            jassert (pushIdx < scratch.getNumChannels());
            return channels [pushIdx++];
        }

        void push (AudioBufferList& bufferList, const int* channelMap) noexcept
        {
            jassert (pushIdx < scratch.getNumChannels());

            if (bufferList.mNumberBuffers > 0)
            {
                const UInt32 n = bufferList.mBuffers [0].mDataByteSize /
                (bufferList.mBuffers [0].mNumberChannels * sizeof (float));
                const bool isInterleaved = isAudioBufferInterleaved (bufferList);
                const int numChannels = static_cast<int> (isInterleaved ? bufferList.mBuffers [0].mNumberChannels
                                                          : bufferList.mNumberBuffers);

                for (int ch = 0; ch < numChannels; ++ch)
                {
                    float* data = push();

                    int mappedChannel = channelMap [ch];
                    if (isInterleaved || static_cast<float*> (bufferList.mBuffers [mappedChannel].mData) != data)
                        copyAudioBuffer (bufferList, mappedChannel, n, data);
                }
            }
        }

        //==============================================================================
        float* pop() noexcept
        {
            jassert (popIdx < scratch.getNumChannels());
            return channels[popIdx++];
        }

        void pop (AudioBufferList& buffer, const int* channelMap) noexcept
        {
            if (buffer.mNumberBuffers > 0)
            {
                const UInt32 n = buffer.mBuffers [0].mDataByteSize / (buffer.mBuffers [0].mNumberChannels * sizeof (float));
                const bool isInterleaved = isAudioBufferInterleaved (buffer);
                const int numChannels = static_cast<int> (isInterleaved ? buffer.mBuffers [0].mNumberChannels : buffer.mNumberBuffers);

                for (int ch = 0; ch < numChannels; ++ch)
                {
                    int mappedChannel = channelMap [ch];
                    float* nextBuffer = pop();

                    if (nextBuffer == buffer.mBuffers [mappedChannel].mData && ! isInterleaved)
                        continue; // no copying necessary

                    if (buffer.mBuffers [mappedChannel].mData == nullptr && ! isInterleaved)
                        buffer.mBuffers [mappedChannel].mData = nextBuffer;
                    else
                        copyAudioBuffer (nextBuffer, mappedChannel, n, buffer);
                }
            }
        }

        //==============================================================================
        AudioSampleBuffer& getBuffer (UInt32 frames) noexcept
        {
            jassert (pushIdx == scratch.getNumChannels());

          #if JUCE_DEBUG
            for (int i = 0; i < pushIdx; ++i)
                jassert (channels [i] != nullptr);
          #endif

            mutableBuffer.setDataToReferTo (channels, pushIdx, static_cast<int> (frames));
            return mutableBuffer;
        }

    private:
        float* uniqueBuffer (int idx, float* buffer) noexcept
        {
            if (buffer == nullptr)
                return scratch.getWritePointer (idx);

            for (int ch = 0; ch < idx; ++ch)
                if (buffer == channels[ch])
                    return scratch.getWritePointer (idx);

            return buffer;
        }

        //==============================================================================
        AudioSampleBuffer scratch;
        AudioSampleBuffer mutableBuffer;

        HeapBlock<float*> channels;
        int pushIdx, popIdx;
    };

    static bool isAudioBufferInterleaved (const AudioBufferList& audioBuffer) noexcept
    {
        return (audioBuffer.mNumberBuffers == 1 && audioBuffer.mBuffers[0].mNumberChannels > 1);
    }

    static void clearAudioBuffer (const AudioBufferList& audioBuffer) noexcept
    {
        for (unsigned int ch = 0; ch < audioBuffer.mNumberBuffers; ++ch)
            zeromem (audioBuffer.mBuffers[ch].mData, audioBuffer.mBuffers[ch].mDataByteSize);
    }

    static void copyAudioBuffer (const AudioBufferList& audioBuffer, const int channel, const UInt32 size, float* dst) noexcept
    {
        if (! isAudioBufferInterleaved (audioBuffer))
        {
            jassert (channel < static_cast<int> (audioBuffer.mNumberBuffers));
            jassert (audioBuffer.mBuffers[channel].mDataByteSize == (size * sizeof (float)));

            memcpy (dst, audioBuffer.mBuffers[channel].mData, size * sizeof (float));
        }
        else
        {
            const int numChannels = static_cast<int> (audioBuffer.mBuffers[0].mNumberChannels);
            const UInt32 n = static_cast<UInt32> (numChannels) * size;
            const float* src = static_cast<const float*> (audioBuffer.mBuffers[0].mData);

            jassert (channel < numChannels);
            jassert (audioBuffer.mBuffers[0].mDataByteSize == (n * sizeof (float)));

            for (const float* inData = src; inData < (src + n); inData += numChannels)
                *dst++ = inData[channel];
        }
    }

    static void copyAudioBuffer (const float *src, const int channel, const UInt32 size, AudioBufferList& audioBuffer) noexcept
    {
        if (! isAudioBufferInterleaved (audioBuffer))
        {
            jassert (channel < static_cast<int> (audioBuffer.mNumberBuffers));
            jassert (audioBuffer.mBuffers[channel].mDataByteSize == (size * sizeof (float)));

            memcpy (audioBuffer.mBuffers[channel].mData, src, size * sizeof (float));
        }
        else
        {
            const int numChannels = static_cast<int> (audioBuffer.mBuffers[0].mNumberChannels);
            const UInt32 n = static_cast<UInt32> (numChannels) * size;
            float* dst = static_cast<float*> (audioBuffer.mBuffers[0].mData);

            jassert (channel < numChannels);
            jassert (audioBuffer.mBuffers[0].mDataByteSize == (n * sizeof (float)));

            for (float* outData = dst; outData < (dst + n); outData += numChannels)
                outData[channel] = *src++;
        }
    }

    template <int numLayouts>
    static bool isLayoutSupported (const AudioProcessor& processor,
                                   bool isInput, int busIdx,
                                   int numChannels,
                                   const short (&channelLayoutList) [numLayouts][2],
                                   bool hasLayoutMap = true)
    {
        if (const AudioProcessor::Bus* bus = processor.getBus (isInput, busIdx))
        {
            if (! bus->isNumberOfChannelsSupported (numChannels))
                return false;

            if (! hasLayoutMap)
                return true;

            const int numConfigs = sizeof (channelLayoutList) / sizeof (short[2]);

            for (int i = 0; i < numConfigs; ++i)
            {
                if (channelLayoutList[i][isInput ? 0 : 1] == numChannels)
                    return true;
            }
        }

        return false;
    }

    static Array<AUChannelInfo> getAUChannelInfo (const AudioProcessor& processor)
    {
        Array<AUChannelInfo> channelInfo;

        auto hasMainInputBus  = (AudioUnitHelpers::getBusCount (&processor, true)  > 0);
        auto hasMainOutputBus = (AudioUnitHelpers::getBusCount (&processor, false) > 0);

        if ((! hasMainInputBus) && (! hasMainOutputBus))
        {
            // midi effect plug-in: no audio
            AUChannelInfo info;
            info.inChannels = 0;
            info.outChannels = 0;

            return { &info, 1 };
        }

        auto layout = processor.getBusesLayout();
        auto maxNumChanToCheckFor = 9;

        auto defaultInputs  = processor.getChannelCountOfBus (true,  0);
        auto defaultOutputs = processor.getChannelCountOfBus (false, 0);

        SortedSet<int> supportedChannels;

        // add the current configuration
        if (defaultInputs != 0 || defaultOutputs != 0)
            supportedChannels.add ((defaultInputs << 16) | defaultOutputs);

        for (auto inChanNum = hasMainInputBus ? 1 : 0; inChanNum <= (hasMainInputBus ? maxNumChanToCheckFor : 0); ++inChanNum)
        {
            auto inLayout = layout;

            if (auto* inBus = processor.getBus (true, 0))
                if (! isNumberOfChannelsSupported (inBus, inChanNum, inLayout))
                    continue;

            for (auto outChanNum = hasMainOutputBus ? 1 : 0; outChanNum <= (hasMainOutputBus ? maxNumChanToCheckFor : 0); ++outChanNum)
            {
                auto outLayout = inLayout;

                if (auto* outBus = processor.getBus (false, 0))
                    if (! isNumberOfChannelsSupported (outBus, outChanNum, outLayout))
                        continue;

                supportedChannels.add (((hasMainInputBus  ? outLayout.getMainInputChannels()  : 0) << 16)
                                      | (hasMainOutputBus ? outLayout.getMainOutputChannels() : 0));
            }
        }

        auto hasInOutMismatch = false;

        for (auto supported : supportedChannels)
        {
            auto numInputs  = (supported >> 16) & 0xffff;
            auto numOutputs = (supported >> 0)  & 0xffff;

            if (numInputs != numOutputs)
            {
                hasInOutMismatch = true;
                break;
            }
        }

        auto hasUnsupportedInput = ! hasMainInputBus, hasUnsupportedOutput = ! hasMainOutputBus;

        for (auto inChanNum = hasMainInputBus ? 1 : 0; inChanNum <= (hasMainInputBus ? maxNumChanToCheckFor : 0); ++inChanNum)
        {
            auto channelConfiguration = (inChanNum << 16) | (hasInOutMismatch ? defaultOutputs : inChanNum);

            if (! supportedChannels.contains (channelConfiguration))
            {
                hasUnsupportedInput = true;
                break;
            }
        }

        for (auto outChanNum = hasMainOutputBus ? 1 : 0; outChanNum <= (hasMainOutputBus ? maxNumChanToCheckFor : 0); ++outChanNum)
        {
            auto channelConfiguration = ((hasInOutMismatch ? defaultInputs : outChanNum) << 16) | outChanNum;

            if (! supportedChannels.contains (channelConfiguration))
            {
                hasUnsupportedOutput = true;
                break;
            }
        }

        for (auto supported : supportedChannels)
        {
            auto numInputs  = (supported >> 16) & 0xffff;
            auto numOutputs = (supported >> 0)  & 0xffff;

            AUChannelInfo info;

            // see here: https://developer.apple.com/library/mac/documentation/MusicAudio/Conceptual/AudioUnitProgrammingGuide/TheAudioUnit/TheAudioUnit.html
            info.inChannels  = static_cast<SInt16> (hasMainInputBus  ? (hasUnsupportedInput  ? numInputs :  (hasInOutMismatch && (! hasUnsupportedOutput) ? -2 : -1)) : 0);
            info.outChannels = static_cast<SInt16> (hasMainOutputBus ? (hasUnsupportedOutput ? numOutputs : (hasInOutMismatch && (! hasUnsupportedInput)  ? -2 : -1)) : 0);

            if (info.inChannels == -2 && info.outChannels == -2)
                info.inChannels = -1;

            int j;
            for (j = 0; j < channelInfo.size(); ++j)
                if (info.inChannels == channelInfo.getReference (j).inChannels
                      && info.outChannels == channelInfo.getReference (j).outChannels)
                    break;

            if (j >= channelInfo.size())
                channelInfo.add (info);
        }

        return channelInfo;
    }

    static bool isNumberOfChannelsSupported (const AudioProcessor::Bus* b, int numChannels, AudioProcessor::BusesLayout& inOutCurrentLayout)
    {
        auto potentialSets = AudioChannelSet::channelSetsWithNumberOfChannels (static_cast<int> (numChannels));

        for (auto set : potentialSets)
        {
            auto copy = inOutCurrentLayout;

            if (b->isLayoutSupported (set, &copy))
            {
                inOutCurrentLayout = copy;
                return true;
            }
        }

        return false;
    }

    //==============================================================================
    static int getBusCount (const AudioProcessor* juceFilter, bool isInput)
    {
        int busCount = juceFilter->getBusCount (isInput);

       #ifdef JucePlugin_PreferredChannelConfigurations
        short configs[][2] = {JucePlugin_PreferredChannelConfigurations};
        const int numConfigs = sizeof (configs) / sizeof (short[2]);

        bool hasOnlyZeroChannels = true;

        for (int i = 0; i < numConfigs && hasOnlyZeroChannels == true; ++i)
            if (configs[i][isInput ? 0 : 1] != 0)
                hasOnlyZeroChannels = false;

        busCount = jmin (busCount, hasOnlyZeroChannels ? 0 : 1);
       #endif

        return busCount;
    }

    static bool setBusesLayout (AudioProcessor* juceFilter, const AudioProcessor::BusesLayout& requestedLayouts)
    {
       #ifdef JucePlugin_PreferredChannelConfigurations
        AudioProcessor::BusesLayout copy (requestedLayouts);

        for (int dir = 0; dir < 2; ++dir)
        {
            const bool isInput = (dir == 0);

            const int actualBuses = juceFilter->getBusCount (isInput);
            const int auNumBuses  = getBusCount (juceFilter, isInput);
            Array<AudioChannelSet>& buses = (isInput ? copy.inputBuses : copy.outputBuses);

            for (int i = auNumBuses; i < actualBuses; ++i)
                buses.add (AudioChannelSet::disabled());
        }

        return juceFilter->setBusesLayout (copy);
       #else
        return juceFilter->setBusesLayout (requestedLayouts);
       #endif
    }

    static AudioProcessor::BusesLayout getBusesLayout (const AudioProcessor* juceFilter)
    {
       #ifdef JucePlugin_PreferredChannelConfigurations
        AudioProcessor::BusesLayout layout = juceFilter->getBusesLayout();

        for (int dir = 0; dir < 2; ++dir)
        {
            const bool isInput = (dir == 0);

            const int actualBuses = juceFilter->getBusCount (isInput);
            const int auNumBuses  = getBusCount (juceFilter, isInput);
            auto& buses = (isInput ? layout.inputBuses : layout.outputBuses);

            for (int i = auNumBuses; i < actualBuses; ++i)
                buses.removeLast();
        }

        return layout;
       #else
        return juceFilter->getBusesLayout();
       #endif
    }
};

} // namespace juce


text:
/*
  ==============================================================================

   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.

  ==============================================================================
*/

namespace juce
{

#if (JUCE_PLUGINHOST_VST3 && (JUCE_MAC || JUCE_WINDOWS)) || DOXYGEN

/**
    Implements a plugin format for VST3s.
*/
class JUCE_API VST3PluginFormat   : public AudioPluginFormat
{
public:
    /** Constructor */
    VST3PluginFormat();

    /** Destructor */
    ~VST3PluginFormat();

    //==============================================================================
    String getName() const override             { return "VST3"; }
    void findAllTypesForFile (OwnedArray<PluginDescription>&, const String& fileOrIdentifier) override;
    bool fileMightContainThisPluginType (const String& fileOrIdentifier) override;
    String getNameOfPluginFromIdentifier (const String& fileOrIdentifier) override;
    bool pluginNeedsRescanning (const PluginDescription&) override;
    StringArray searchPathsForPlugins (const FileSearchPath&, bool recursive, bool) override;
    bool doesPluginStillExist (const PluginDescription&) override;
    FileSearchPath getDefaultLocationsToSearch() override;
    bool canScanForPlugins() const override     { return true; }

private:
    void createPluginInstance (const PluginDescription&, double initialSampleRate,
                               int initialBufferSize, void* userData,
                               void (*callback) (void*, AudioPluginInstance*, const String&)) override;

    bool requiresUnblockedMessageThreadDuringCreation (const PluginDescription&) const noexcept override;

private:
    //==============================================================================
    void recursiveFileSearch (StringArray&, const File&, bool recursive);

    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (VST3PluginFormat)
};

#endif // JUCE_PLUGINHOST_VST3

} // namespace juce


text:
/*
  ==============================================================================

   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.

  ==============================================================================
*/

#define JUCE_VSTINTERFACE_H_INCLUDED

using namespace juce;

#if JUCE_MSVC
 #define VSTINTERFACECALL __cdecl
 #pragma pack(push)
 #pragma pack(8)
#elif JUCE_MAC || JUCE_IOS
 #define VSTINTERFACECALL
 #if JUCE_64BIT
  #pragma options align=power
 #else
  #pragma options align=mac68k
 #endif
#else
 #define VSTINTERFACECALL
 #pragma pack(push, 8)
#endif

const int32 juceVstInterfaceVersion = 2400;
const int32 juceVstInterfaceIdentifier = 0x56737450;    // The "magic" identifier in the SDK is 'VstP'.

//==============================================================================
struct VstEffectInterface
{
    int32 interfaceIdentifier;
    pointer_sized_int (VSTINTERFACECALL* dispatchFunction)          (VstEffectInterface*, int32 op, int32 index, pointer_sized_int value, void* ptr, float opt);
    void              (VSTINTERFACECALL* processAudioFunction)      (VstEffectInterface*, float** inputs, float** outputs, int32 numSamples);
    void              (VSTINTERFACECALL* setParameterValueFunction) (VstEffectInterface*, int32 parameterIndex, float value);
    float             (VSTINTERFACECALL* getParameterValueFunction) (VstEffectInterface*, int32 parameterIndex);
    int32 numPrograms;
    int32 numParameters;
    int32 numInputChannels;
    int32 numOutputChannels;
    int32 flags;
    pointer_sized_int hostSpace1;
    pointer_sized_int hostSpace2;
    int32 latency;
    int32 deprecated1;
    int32 deprecated2;
    float deprecated3;
    void* effectPointer;
    void* userPointer;
    int32 plugInIdentifier;
    int32 plugInVersion;
    void (VSTINTERFACECALL* processAudioInplaceFunction)       (VstEffectInterface*, float**  inputs, float**  outputs, int32 numSamples);
    void (VSTINTERFACECALL* processDoubleAudioInplaceFunction) (VstEffectInterface*, double** inputs, double** outputs, int32 numSamples);
    char emptySpace[56];
};

typedef pointer_sized_int (VSTINTERFACECALL* VstHostCallback) (VstEffectInterface*, int32 op, int32 index, pointer_sized_int value, void* ptr, float opt);

enum VstEffectInterfaceFlags
{
    vstEffectFlagHasEditor          = 1,
    vstEffectFlagInplaceAudio       = 16,
    vstEffectFlagDataInChunks       = 32,
    vstEffectFlagIsSynth            = 256,
    vstEffectFlagInplaceDoubleAudio = 4096
};

//==============================================================================
enum VstHostToPlugInOpcodes
{
    plugInOpcodeOpen,
    plugInOpcodeClose,
    plugInOpcodeSetCurrentProgram,
    plugInOpcodeGetCurrentProgram,
    plugInOpcodeSetCurrentProgramName,
    plugInOpcodeGetCurrentProgramName,
    plugInOpcodeGetParameterLabel,
    plugInOpcodeGetParameterText,
    plugInOpcodeGetParameterName,
    plugInOpcodeSetSampleRate = plugInOpcodeGetParameterName + 2,
    plugInOpcodeSetBlockSize,
    plugInOpcodeResumeSuspend,
    plugInOpcodeGetEditorBounds,
    plugInOpcodeOpenEditor,
    plugInOpcodeCloseEditor,
    plugInOpcodeDrawEditor,
    plugInOpcodeGetMouse,
    plugInOpcodeEditorIdle = plugInOpcodeGetMouse + 2,
    plugInOpcodeeffEditorTop,
    plugInOpcodeSleepEditor,
    plugInOpcodeIdentify,
    plugInOpcodeGetData,
    plugInOpcodeSetData,
    plugInOpcodePreAudioProcessingEvents,
    plugInOpcodeIsParameterAutomatable,
    plugInOpcodeParameterValueForText,
    plugInOpcodeGetProgramName = plugInOpcodeParameterValueForText + 2,
    plugInOpcodeConnectInput = plugInOpcodeGetProgramName + 2,
    plugInOpcodeConnectOutput,
    plugInOpcodeGetInputPinProperties,
    plugInOpcodeGetOutputPinProperties,
    plugInOpcodeGetPlugInCategory,
    plugInOpcodeSetSpeakerConfiguration = plugInOpcodeGetPlugInCategory + 7,
    plugInOpcodeSetBypass = plugInOpcodeSetSpeakerConfiguration + 2,
    plugInOpcodeGetPlugInName,
    plugInOpcodeGetManufacturerName = plugInOpcodeGetPlugInName + 2,
    plugInOpcodeGetManufacturerProductName,
    plugInOpcodeGetManufacturerVersion,
    plugInOpcodeManufacturerSpecific,
    plugInOpcodeCanPlugInDo,
    plugInOpcodeGetTailSize,
    plugInOpcodeIdle,
    plugInOpcodeKeyboardFocusRequired = plugInOpcodeIdle + 4,
    plugInOpcodeGetVstInterfaceVersion,
    plugInOpcodeGetCurrentMidiProgram = plugInOpcodeGetVstInterfaceVersion + 5,
    plugInOpcodeGetSpeakerArrangement = plugInOpcodeGetCurrentMidiProgram + 6,
    plugInOpcodeNextPlugInUniqueID,
    plugInOpcodeStartProcess,
    plugInOpcodeStopProcess,
    plugInOpcodeSetNumberOfSamplesToProcess,
    plugInOpcodeSetSampleFloatType = plugInOpcodeSetNumberOfSamplesToProcess + 4,
    pluginOpcodeGetNumMidiInputChannels,
    pluginOpcodeGetNumMidiOutputChannels,
    plugInOpcodeMaximum = pluginOpcodeGetNumMidiOutputChannels
};

enum VstPlugInToHostOpcodes
{
    hostOpcodeParameterChanged,
    hostOpcodeVstVersion,
    hostOpcodeCurrentId,
    hostOpcodeIdle,
    hostOpcodePinConnected,
    hostOpcodePlugInWantsMidi = hostOpcodePinConnected + 2,
    hostOpcodeGetTimingInfo,
    hostOpcodePreAudioProcessingEvents,
    hostOpcodeSetTime,
    hostOpcodeTempoAt,
    hostOpcodeGetNumberOfAutomatableParameters,
    hostOpcodeGetParameterInterval,
    hostOpcodeIOModified,
    hostOpcodeNeedsIdle,
    hostOpcodeWindowSize,
    hostOpcodeGetSampleRate,
    hostOpcodeGetBlockSize,
    hostOpcodeGetInputLatency,
    hostOpcodeGetOutputLatency,
    hostOpcodeGetPreviousPlugIn,
    hostOpcodeGetNextPlugIn,
    hostOpcodeWillReplace,
    hostOpcodeGetCurrentAudioProcessingLevel,
    hostOpcodeGetAutomationState,
    hostOpcodeOfflineStart,
    hostOpcodeOfflineReadSource,
    hostOpcodeOfflineWrite,
    hostOpcodeOfflineGetCurrentPass,
    hostOpcodeOfflineGetCurrentMetaPass,
    hostOpcodeSetOutputSampleRate,
    hostOpcodeGetOutputSpeakerConfiguration,
    hostOpcodeGetManufacturerName,
    hostOpcodeGetProductName,
    hostOpcodeGetManufacturerVersion,
    hostOpcodeManufacturerSpecific,
    hostOpcodeSetIcon,
    hostOpcodeCanHostDo,
    hostOpcodeGetLanguage,
    hostOpcodeOpenEditorWindow,
    hostOpcodeCloseEditorWindow,
    hostOpcodeGetDirectory,
    hostOpcodeUpdateView,
    hostOpcodeParameterChangeGestureBegin,
    hostOpcodeParameterChangeGestureEnd,
};

//==============================================================================
enum VstProcessingSampleType
{
    vstProcessingSampleTypeFloat,
    vstProcessingSampleTypeDouble
};

//==============================================================================
// These names must be identical to the Steinberg SDK so JUCE users can set
// exactly what they want.
enum VstPlugInCategory
{
    kPlugCategUnknown,
    kPlugCategEffect,
    kPlugCategSynth,
    kPlugCategAnalysis,
    kPlugCategMastering,
    kPlugCategSpacializer,
    kPlugCategRoomFx,
    kPlugSurroundFx,
    kPlugCategRestoration,
    kPlugCategOfflineProcess,
    kPlugCategShell,
    kPlugCategGenerator
};

//==============================================================================
struct VstEditorBounds
{
    int16 upper;
    int16 leftmost;
    int16 lower;
    int16 rightmost;
};

//==============================================================================
enum VstMaxStringLengths
{
    vstMaxNameLength                     = 64,
    vstMaxParameterOrPinLabelLength      = 64,
    vstMaxParameterOrPinShortLabelLength = 8,
    vstMaxCategoryLength                 = 24,
    vstMaxManufacturerStringLength       = 64,
    vstMaxPlugInNameStringLength         = 64
};

//==============================================================================
struct VstPinInfo
{
    char text[vstMaxParameterOrPinLabelLength];
    int32 flags;
    int32 configurationType;
    char shortText[vstMaxParameterOrPinShortLabelLength];
    char unused[48];
};

enum VstPinInfoFlags
{
    vstPinInfoFlagIsActive = 1,
    vstPinInfoFlagIsStereo = 2,
    vstPinInfoFlagValid    = 4
};

//==============================================================================
struct VstEvent
{
    int32 type;
    int32 size;
    int32 sampleOffset;
    int32 flags;
    char content[16];
};

enum VstEventTypes
{
    vstMidiEventType  = 1,
    vstSysExEventType = 6
};

struct VstEventBlock
{
    int32 numberOfEvents;
    pointer_sized_int future;
    VstEvent* events[2];
};

struct VstMidiEvent
{
    int32 type;
    int32 size;
    int32 sampleOffset;
    int32 flags;
    int32 noteSampleLength;
    int32 noteSampleOffset;
    char midiData[4];
    char tuning;
    char noteVelocityOff;
    char future1;
    char future2;
};

enum VstMidiEventFlags
{
    vstMidiEventIsRealtime = 1
};

struct VstSysExEvent
{
    int32 type;
    int32 size;
    int32 offsetSamples;
    int32 flags;
    int32 sysExDumpSize;
    pointer_sized_int future1;
    char* sysExDump;
    pointer_sized_int future2;
};

//==============================================================================
struct VstTimingInformation
{
    double samplePosition;
    double sampleRate;
    double systemTimeNanoseconds;
    double musicalPosition;
    double tempoBPM;
    double lastBarPosition;
    double loopStartPosition;
    double loopEndPosition;
    int32 timeSignatureNumerator;
    int32 timeSignatureDenominator;
    int32 smpteOffset;
    int32 smpteRate;
    int32 samplesToNearestClock;
    int32 flags;
};

enum VstTimingInformationFlags
{
    vstTimingInfoFlagTransportChanged          = 1,
    vstTimingInfoFlagCurrentlyPlaying          = 2,
    vstTimingInfoFlagLoopActive                = 4,
    vstTimingInfoFlagCurrentlyRecording        = 8,
    vstTimingInfoFlagAutomationWriteModeActive = 64,
    vstTimingInfoFlagAutomationReadModeActive  = 128,
    vstTimingInfoFlagNanosecondsValid          = 256,
    vstTimingInfoFlagMusicalPositionValid      = 512,
    vstTimingInfoFlagTempoValid                = 1024,
    vstTimingInfoFlagLastBarPositionValid      = 2048,
    vstTimingInfoFlagLoopPositionValid         = 4096,
    vstTimingInfoFlagTimeSignatureValid        = 8192,
    vstTimingInfoFlagSmpteValid                = 16384,
    vstTimingInfoFlagNearestClockValid         = 32768
};

//==============================================================================
enum VstSmpteRates
{
    vstSmpteRateFps24,
    vstSmpteRateFps25,
    vstSmpteRateFps2997,
    vstSmpteRateFps30,
    vstSmpteRateFps2997drop,
    vstSmpteRateFps30drop,

    vstSmpteRate16mmFilm,
    vstSmpteRate35mmFilm,

    vstSmpteRateFps239 = vstSmpteRate35mmFilm + 3,
    vstSmpteRateFps249 ,
    vstSmpteRateFps599,
    vstSmpteRateFps60
};

//==============================================================================
struct VstIndividualSpeakerInfo
{
    float azimuthalAngle;
    float elevationAngle;
    float radius;
    float reserved;
    char label[vstMaxNameLength];
    int32 type;
    char unused[28];
};

enum VstIndividualSpeakerType
{
    vstIndividualSpeakerTypeUndefined = 0x7fffffff,
    vstIndividualSpeakerTypeMono = 0,
    vstIndividualSpeakerTypeLeft,
    vstIndividualSpeakerTypeRight,
    vstIndividualSpeakerTypeCentre,
    vstIndividualSpeakerTypeLFE,
    vstIndividualSpeakerTypeLeftSurround,
    vstIndividualSpeakerTypeRightSurround,
    vstIndividualSpeakerTypeLeftCentre,
    vstIndividualSpeakerTypeRightCentre,
    vstIndividualSpeakerTypeSurround,
    vstIndividualSpeakerTypeCentreSurround = vstIndividualSpeakerTypeSurround,
    vstIndividualSpeakerTypeLeftRearSurround,
    vstIndividualSpeakerTypeRightRearSurround,
    vstIndividualSpeakerTypeTopMiddle,
    vstIndividualSpeakerTypeTopFrontLeft,
    vstIndividualSpeakerTypeTopFrontCentre,
    vstIndividualSpeakerTypeTopFrontRight,
    vstIndividualSpeakerTypeTopRearLeft,
    vstIndividualSpeakerTypeTopRearCentre,
    vstIndividualSpeakerTypeTopRearRight,
    vstIndividualSpeakerTypeLFE2
};

struct VstSpeakerConfiguration
{
    int32 type;
    int32 numberOfChannels;
    VstIndividualSpeakerInfo speakers[8];
};

enum VstSpeakerConfigurationType
{
    vstSpeakerConfigTypeUser  = -2,
    vstSpeakerConfigTypeEmpty = -1,
    vstSpeakerConfigTypeMono  = 0,
    vstSpeakerConfigTypeLR,
    vstSpeakerConfigTypeLsRs,
    vstSpeakerConfigTypeLcRc,
    vstSpeakerConfigTypeSlSr,
    vstSpeakerConfigTypeCLfe,
    vstSpeakerConfigTypeLRC,
    vstSpeakerConfigTypeLRS,
    vstSpeakerConfigTypeLRCLfe,
    vstSpeakerConfigTypeLRLfeS,
    vstSpeakerConfigTypeLRCS,
    vstSpeakerConfigTypeLRLsRs,
    vstSpeakerConfigTypeLRCLfeS,
    vstSpeakerConfigTypeLRLfeLsRs,
    vstSpeakerConfigTypeLRCLsRs,
    vstSpeakerConfigTypeLRCLfeLsRs,
    vstSpeakerConfigTypeLRCLsRsCs,
    vstSpeakerConfigTypeLRLsRsSlSr,
    vstSpeakerConfigTypeLRCLfeLsRsCs,
    vstSpeakerConfigTypeLRLfeLsRsSlSr,
    vstSpeakerConfigTypeLRCLsRsLcRc,
    vstSpeakerConfigTypeLRCLsRsSlSr,
    vstSpeakerConfigTypeLRCLfeLsRsLcRc,
    vstSpeakerConfigTypeLRCLfeLsRsSlSr,
    vstSpeakerConfigTypeLRCLsRsLcRcCs,
    vstSpeakerConfigTypeLRCLsRsCsSlSr,
    vstSpeakerConfigTypeLRCLfeLsRsLcRcCs,
    vstSpeakerConfigTypeLRCLfeLsRsCsSlSr,
    vstSpeakerConfigTypeLRCLfeLsRsTflTfcTfrTrlTrrLfe2
};

#if JUCE_BIG_ENDIAN
 #define JUCE_MULTICHAR_CONSTANT(a, b, c, d) (a | (((uint32) b) << 8) | (((uint32) c) << 16) | (((uint32) d) << 24))
#else
 #define JUCE_MULTICHAR_CONSTANT(a, b, c, d) (d | (((uint32) c) << 8) | (((uint32) b) << 16) | (((uint32) a) << 24))
#endif

enum PresonusExtensionConstants
{
    presonusVendorID                = JUCE_MULTICHAR_CONSTANT ('P', 'r', 'e', 'S'),
    presonusSetContentScaleFactor   = JUCE_MULTICHAR_CONSTANT ('A', 'e', 'C', 's')
};

//==============================================================================
struct vst2FxBank
{
    int32 magic1;
    int32 size;
    int32 magic2;
    int32 version1;
    int32 fxID;
    int32 version2;
    int32 elements;
    int32 current;
    char shouldBeZero[124];
    int32 chunkSize;
    char chunk[1];
};

#if JUCE_MSVC
 #pragma pack(pop)
#elif JUCE_MAC || JUCE_IOS
 #pragma options align=reset
#else
 #pragma pack(pop)
#endif