|
- /*
- ==============================================================================
-
- This file is part of the JUCE library - "Jules' Utility Class Extensions"
- Copyright 2004-11 by Raw Material Software Ltd.
-
- ------------------------------------------------------------------------------
-
- JUCE can be redistributed and/or modified under the terms of the GNU General
- Public License (Version 2), as published by the Free Software Foundation.
- A copy of the license is included in the JUCE distribution, or can be found
- online at www.gnu.org/licenses.
-
- JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
- ------------------------------------------------------------------------------
-
- To release a closed-source product which uses JUCE, commercial licenses are
- available: visit www.rawmaterialsoftware.com/juce for more information.
-
- ==============================================================================
- */
-
- // Your project must contain an AppConfig.h file with your project-specific settings in it,
- // and your header search path must make it accessible to the module's files.
- #include "AppConfig.h"
-
- #include "../utility/juce_CheckSettingMacros.h"
-
- #if JucePlugin_Build_AAX && (JUCE_INCLUDED_AAX_IN_MM || JUCE_WINDOWS)
-
- #if JUCE_MAC
- #include <Cocoa/Cocoa.h>
- #endif
-
- #include "../utility/juce_IncludeModuleHeaders.h"
- #undef Component
-
- #include "AAX_Exports.cpp"
- #include "AAX_ICollection.h"
- #include "AAX_IComponentDescriptor.h"
- #include "AAX_IEffectDescriptor.h"
- #include "AAX_IPropertyMap.h"
- #include "AAX_CEffectParameters.h"
- #include "AAX_Errors.h"
- #include "AAX_CBinaryTaperDelegate.h"
- #include "AAX_CBinaryDisplayDelegate.h"
- #include "AAX_CEffectGUI.h"
-
- #if JUCE_WINDOWS
- static HINSTANCE moduleInstance = 0;
-
- extern "C" BOOL WINAPI DllMain (HINSTANCE instance, DWORD selector, LPVOID)
- {
- if (selector == DLL_PROCESS_ATTACH)
- moduleInstance = instance;
-
- return true;
- }
- #endif
-
- //==============================================================================
- /** Somewhere in the codebase of your plugin, you need to implement this function
- and make it return a new instance of the filter subclass that you're building.
- */
- extern AudioProcessor* JUCE_CALLTYPE createPluginFilter();
-
- //==============================================================================
- struct AAXClasses
- {
- static void check (AAX_Result result)
- {
- jassert (result == AAX_SUCCESS);
- }
-
- struct FourCharConst
- {
- FourCharConst (const uint32 n) noexcept
- {
- asString[0] = (char) (n >> 24);
- asString[1] = (char) (n >> 16);
- asString[2] = (char) (n >> 8);
- asString[3] = (char) n;
- asString[4] = 0;
- }
-
- char asString[5];
- };
-
- static AAX_EStemFormat getFormatForChans (const int numChans) noexcept
- {
- switch (numChans)
- {
- case 0: return AAX_eStemFormat_None;
- case 1: return AAX_eStemFormat_Mono;
- case 2: return AAX_eStemFormat_Stereo;
- case 3: return AAX_eStemFormat_LCR;
- case 4: return AAX_eStemFormat_Quad;
- case 5: return AAX_eStemFormat_5_0;
- case 6: return AAX_eStemFormat_5_1;
- case 7: return AAX_eStemFormat_6_1;
- case 8: return AAX_eStemFormat_7_1_DTS;
-
- default: jassertfalse; break; // hmm - not a valid number of chans..
- }
-
- return AAX_eStemFormat_None;
- }
-
- static int getNumChannelsForStemFormat (AAX_EStemFormat format) noexcept
- {
- switch (format)
- {
- case AAX_eStemFormat_None: return 0;
- case AAX_eStemFormat_Mono: return 1;
- case AAX_eStemFormat_Stereo: return 2;
- case AAX_eStemFormat_LCR: return 3;
- case AAX_eStemFormat_Quad: return 4;
- case AAX_eStemFormat_5_0: return 5;
- case AAX_eStemFormat_5_1: return 6;
- case AAX_eStemFormat_6_1: return 7;
- case AAX_eStemFormat_7_1_DTS: return 8;
- default: jassertfalse; break; // hmm - not a valid number of chans..
- }
-
- return 0;
- }
-
- //==============================================================================
- struct JUCELibraryRefCount
- {
- JUCELibraryRefCount() { if (getCount()++ == 0) initialise(); }
- ~JUCELibraryRefCount() { if (--getCount() == 0) shutdown(); }
-
- private:
- static void initialise()
- {
- #if JUCE_WINDOWS
- PlatformUtilities::setCurrentModuleInstanceHandle (moduleInstance);
- #endif
-
- initialiseJuce_GUI();
- }
-
- static void shutdown()
- {
- shutdownJuce_GUI();
- }
-
- int& getCount() noexcept
- {
- static int count = 0;
- return count;
- }
- };
-
- //==============================================================================
- struct PluginInstanceInfo
- {
- PluginInstanceInfo (AudioProcessor* pluginInstance_)
- : pluginInstance (pluginInstance_)
- {
- }
-
- void process (float* const* inputs, float* const* outputs, const int bufferSize)
- {
- const int numIns = pluginInstance->getNumInputChannels();
- const int numOuts = pluginInstance->getNumOutputChannels();
- const int bufferBytes = bufferSize * sizeof (float);
-
- float* const* renderingChannels = inputs;
- int numChans = numIns;
-
- if (numOuts > numIns)
- {
- for (int i = 0; i < numIns; ++i)
- memcpy (outputs[i], inputs[i], bufferBytes);
-
- renderingChannels = outputs;
- numChans = numOuts;
- }
-
- AudioSampleBuffer buffer (renderingChannels, jmax (1, numChans), bufferSize);
-
- // XXX need to do midi..
- midiBuffer.clear();
-
- {
- const ScopedLock sl (pluginInstance->getCallbackLock());
- pluginInstance->processBlock (buffer, midiBuffer);
- }
-
- if (numOuts <= numIns)
- {
- for (int i = 0; i < numOuts; ++i)
- memcpy (outputs[i], inputs[i], bufferBytes);
- }
- }
-
- void bypass (float* const* inputs, float* const* outputs, int bufferSize)
- {
- const int numIns = pluginInstance->getNumInputChannels();
- const int numOuts = pluginInstance->getNumOutputChannels();
-
- for (int i = 0; i < numOuts; ++i)
- {
- if (i < numIns)
- memcpy (outputs[i], inputs[i], sizeof (float) * bufferSize);
- else
- zeromem (outputs[i], sizeof (float) * bufferSize);
- }
- }
-
- AudioProcessor* pluginInstance;
- MidiBuffer midiBuffer;
-
- JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PluginInstanceInfo);
- };
-
- //==============================================================================
- struct JUCEAlgorithmContext
- {
- float* const* inputChannels;
- float* const* outputChannels;
- int32_t* bufferSize;
- int32_t* bypass;
-
- PluginInstanceInfo* pluginInstance;
- int32_t* isPrepared;
- };
-
- struct JUCEAlgorithmIDs
- {
- enum
- {
- inputChannels = AAX_FIELD_INDEX (JUCEAlgorithmContext, inputChannels),
- outputChannels = AAX_FIELD_INDEX (JUCEAlgorithmContext, outputChannels),
- bufferSize = AAX_FIELD_INDEX (JUCEAlgorithmContext, bufferSize),
- bypass = AAX_FIELD_INDEX (JUCEAlgorithmContext, bypass),
- pluginInstance = AAX_FIELD_INDEX (JUCEAlgorithmContext, pluginInstance),
- preparedFlag = AAX_FIELD_INDEX (JUCEAlgorithmContext, isPrepared)
- };
- };
-
- //==============================================================================
- class JuceAAX_GUI : public AAX_CEffectGUI
- {
- public:
- JuceAAX_GUI() {}
- virtual ~JuceAAX_GUI() { DeleteViewContainer(); }
-
- static AAX_IEffectGUI* AAX_CALLBACK Create() { return new JuceAAX_GUI(); }
-
- void CreateViewContents()
- {
- if (component == nullptr)
- {
- JuceAAX_Parameters* params = dynamic_cast <JuceAAX_Parameters*> (GetEffectParameters());
- jassert (params != nullptr);
-
- if (params != nullptr)
- component = new ContentWrapperComponent (params->getPluginInstance());
- }
- }
-
- void CreateViewContainer()
- {
- CreateViewContents();
- void* nativeViewToAttachTo = GetViewContainerPtr();
-
- if (nativeViewToAttachTo != nullptr)
- {
- #if JUCE_MAC
- if (GetViewContainerType() == AAX_eViewContainer_Type_NSView)
- #else
- if (GetViewContainerType() == AAX_eViewContainer_Type_HWND)
- #endif
- {
- component->setVisible (true);
- component->addToDesktop (0, nativeViewToAttachTo);
- }
- }
- }
-
- void DeleteViewContainer()
- {
- if (component != nullptr)
- {
- JUCE_AUTORELEASEPOOL
- component->removeFromDesktop();
- component = nullptr;
- }
- }
-
- virtual AAX_Result GetViewSize (AAX_Point* const viewSize) const
- {
- if (component != nullptr)
- {
- viewSize->horz = (float) component->getWidth();
- viewSize->vert = (float) component->getHeight();
- return AAX_SUCCESS;
- }
-
- return AAX_ERROR_NULL_OBJECT;
- }
-
- AAX_Result ParameterUpdated (AAX_CParamID iParameterID)
- {
-
- return AAX_SUCCESS;
- }
-
- AAX_Result SetControlHighlightInfo (AAX_CParamID iParameterID, AAX_CBoolean iIsHighlighted, AAX_EHighlightColor iColor)
- {
-
- return AAX_SUCCESS;
- }
-
- private:
- class ContentWrapperComponent : public Component
- {
- public:
- ContentWrapperComponent (AudioProcessor* plugin)
- {
- setOpaque (true);
- addAndMakeVisible (pluginEditor = plugin->createEditor());
- }
-
- ~ContentWrapperComponent()
- {
- if (pluginEditor != nullptr)
- {
- PopupMenu::dismissAllActiveMenus();
- pluginEditor->getAudioProcessor()->editorBeingDeleted (pluginEditor);
- }
- }
-
- void paint (Graphics& g)
- {
- g.fillAll (Colours::pink);
- }
-
- void resized()
- {
- if (pluginEditor != nullptr)
- pluginEditor->setBounds (getLocalBounds());
- }
-
- private:
- ScopedPointer<AudioProcessorEditor> pluginEditor;
-
- JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ContentWrapperComponent);
- };
-
- ScopedPointer<ContentWrapperComponent> component;
-
- JUCELibraryRefCount juceCount;
- JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (JuceAAX_GUI);
- };
-
- //==============================================================================
- class JuceAAX_Parameters : public AAX_CEffectParameters
- {
- public:
- JuceAAX_Parameters()
- {
- pluginInstance = createPluginFilter();
- }
-
- static AAX_CEffectParameters* AAX_CALLBACK Create() { return new JuceAAX_Parameters(); }
-
- AAX_Result EffectInit()
- {
- addBypassParameter();
-
- // add other params..
-
- preparePlugin();
-
- return AAX_SUCCESS;
- }
-
- AAX_Result ResetFieldData (AAX_CFieldIndex fieldIndex, void* data, uint32_t dataSize) const
- {
- switch (fieldIndex)
- {
- case JUCEAlgorithmIDs::pluginInstance:
- {
- const size_t numObjects = dataSize / sizeof (PluginInstanceInfo);
- PluginInstanceInfo* const objects = static_cast <PluginInstanceInfo*> (data);
-
- jassert (numObjects == 1); // not sure how to handle more than one..
-
- for (size_t i = 0; i < numObjects; ++i)
- new (objects + i) PluginInstanceInfo (pluginInstance);
-
- break;
- }
-
- case JUCEAlgorithmIDs::preparedFlag:
- {
- preparePlugin();
-
- const size_t numObjects = dataSize / sizeof (uint32_t);
- uint32_t* const objects = static_cast <uint32_t*> (data);
-
- for (size_t i = 0; i < numObjects; ++i)
- new (objects + i) uint32_t (1);
-
- break;
- }
- }
-
- return AAX_SUCCESS;
- //return AAX_ERROR_INVALID_FIELD_INDEX;
- }
-
- AudioProcessor* getPluginInstance() const noexcept { return pluginInstance; }
-
- private:
- void addBypassParameter()
- {
- AAX_CString bypassID;
- GetMasterBypassParameter (&bypassID);
-
- AAX_IParameter* masterBypass = new AAX_CParameter<bool> (bypassID.CString(),
- AAX_CString ("Master Bypass"),
- false,
- AAX_CBinaryTaperDelegate<bool>(),
- AAX_CBinaryDisplayDelegate<bool> ("bypass", "on"),
- true);
- masterBypass->SetNumberOfSteps (2);
- masterBypass->SetType (AAX_eParameterType_Discrete);
- mParameterManager.AddParameter (masterBypass);
- mPacketDispatcher.RegisterPacket (bypassID.CString(), JUCEAlgorithmIDs::bypass);
- }
-
- void preparePlugin() const
- {
- AAX_CSampleRate sampleRate;
- check (Controller()->GetSampleRate (&sampleRate));
-
- AAX_EStemFormat inputStemFormat = AAX_eStemFormat_None;
- check (Controller()->GetInputStemFormat (&inputStemFormat));
- const int numberOfInputChannels = getNumChannelsForStemFormat (inputStemFormat);
-
- AAX_EStemFormat outputStemFormat = AAX_eStemFormat_None;
- check (Controller()->GetOutputStemFormat (&outputStemFormat));
- const int numberOfOutputChannels = getNumChannelsForStemFormat (outputStemFormat);
-
- int32_t bufferSize = 0;
- check (Controller()->GetSignalLatency (&bufferSize));
-
- AudioProcessor* audioProcessor = getPluginInstance();
- audioProcessor->setPlayConfigDetails (numberOfInputChannels, numberOfOutputChannels, sampleRate, bufferSize);
- audioProcessor->prepareToPlay (sampleRate, bufferSize);
- }
-
- JUCELibraryRefCount juceCount;
-
- ScopedPointer<AudioProcessor> pluginInstance;
-
- JUCE_DECLARE_NON_COPYABLE (JuceAAX_Parameters);
- };
-
- //==============================================================================
- static void AAX_CALLBACK algorithmProcessCallback (JUCEAlgorithmContext* const instancesBegin[],
- const void* const instancesEnd)
- {
- for (JUCEAlgorithmContext* const* iter = instancesBegin; iter < instancesEnd; ++iter)
- {
- const JUCEAlgorithmContext& i = **iter;
-
- if (*(i.bypass) != 0)
- i.pluginInstance->bypass (i.inputChannels, i.outputChannels, *(i.bufferSize));
- else
- i.pluginInstance->process (i.inputChannels, i.outputChannels, *(i.bufferSize));
- }
- }
-
- //==============================================================================
- static void createDescriptor (AAX_IComponentDescriptor& desc, int numInputs, int numOutputs)
- {
- check (desc.AddAudioIn (JUCEAlgorithmIDs::inputChannels));
- check (desc.AddAudioOut (JUCEAlgorithmIDs::outputChannels));
- check (desc.AddAudioBufferLength (JUCEAlgorithmIDs::bufferSize));
- check (desc.AddDataInPort (JUCEAlgorithmIDs::bypass, sizeof (int32_t)));
-
- check (desc.AddPrivateData (JUCEAlgorithmIDs::pluginInstance, sizeof (PluginInstanceInfo)));
-
- // Create a property map
- AAX_IPropertyMap* const properties = desc.NewPropertyMap();
- jassert (properties != nullptr);
-
- properties->AddProperty (AAX_eProperty_ManufacturerID, JucePlugin_AAXManufacturerCode);
- properties->AddProperty (AAX_eProperty_ProductID, JucePlugin_AAXProductId);
- properties->AddProperty (AAX_eProperty_CanBypass, true);
-
- properties->AddProperty (AAX_eProperty_InputStemFormat, getFormatForChans (numInputs));
- properties->AddProperty (AAX_eProperty_OutputStemFormat, getFormatForChans (numOutputs));
-
- properties->AddProperty (AAX_eProperty_PlugInID_Native, JucePlugin_AAXPluginId + (numInputs + 256 * numOutputs));
-
- check (desc.AddProcessProc_Native (algorithmProcessCallback, properties));
- }
-
- static void getPlugInDescription (AAX_IEffectDescriptor& descriptor)
- {
- descriptor.AddName (JucePlugin_Desc);
- descriptor.AddName (JucePlugin_Name);
- descriptor.AddName (FourCharConst (JucePlugin_PluginCode).asString);
- descriptor.AddCategory (JucePlugin_AAXCategory);
-
- check (descriptor.AddProcPtr ((void*) JuceAAX_GUI::Create, kAAX_ProcPtrID_Create_EffectGUI));
- check (descriptor.AddProcPtr ((void*) JuceAAX_Parameters::Create, kAAX_ProcPtrID_Create_EffectParameters));
-
- const short channelConfigs[][2] = { JucePlugin_PreferredChannelConfigurations };
- const int numConfigs = numElementsInArray (channelConfigs);
-
- // You need to actually add some configurations to the JucePlugin_PreferredChannelConfigurations
- // value in your JucePluginCharacteristics.h file..
- jassert (numConfigs > 0);
-
- for (int i = 0; i < numConfigs; ++i)
- {
- AAX_IComponentDescriptor* const desc = descriptor.NewComponentDescriptor();
-
- if (desc != nullptr)
- {
- createDescriptor (*desc,
- channelConfigs [i][0],
- channelConfigs [i][1]);
-
- check (descriptor.AddComponent (desc));
- }
- }
- }
- };
-
- //==============================================================================
- AAX_Result JUCE_CDECL GetEffectDescriptions (AAX_ICollection* const collection)
- {
- AAXClasses::JUCELibraryRefCount libraryRefCount;
-
- AAX_IEffectDescriptor* const descriptor = collection->NewDescriptor();
- if (descriptor == nullptr)
- return AAX_ERROR_NULL_OBJECT;
-
- AAXClasses::getPlugInDescription (*descriptor);
- collection->AddEffect (JUCE_STRINGIFY (JucePlugin_AAXIdentifier), descriptor);
-
- collection->SetManufacturerName (JucePlugin_Manufacturer);
- collection->AddPackageName (JucePlugin_Desc);
- collection->AddPackageName (JucePlugin_Name);
- collection->AddPackageName (AAXClasses::FourCharConst (JucePlugin_PluginCode).asString);
- collection->SetPackageVersion (JucePlugin_VersionCode);
-
- return AAX_SUCCESS;
- }
-
- #endif
|