Browse Source

Plugin Client: Remove unnecessary wrapper files

v7.0.9
reuk 2 years ago
parent
commit
33ef4a86f4
No known key found for this signature in database GPG Key ID: FCB43929F012EE5C
31 changed files with 16456 additions and 16807 deletions
  1. +0
    -11
      extras/Build/CMake/JUCEModuleSupport.cmake
  2. +1
    -1
      extras/Build/CMake/JUCEUtils.cmake
  3. +0
    -2584
      modules/juce_audio_plugin_client/AAX/juce_AAX_Wrapper.cpp
  4. +0
    -45
      modules/juce_audio_plugin_client/ARA/juce_ARA_Wrapper.cpp
  5. +0
    -2620
      modules/juce_audio_plugin_client/AU/juce_AU_Wrapper.mm
  6. +0
    -2013
      modules/juce_audio_plugin_client/AU/juce_AUv3_Wrapper.mm
  7. +0
    -1815
      modules/juce_audio_plugin_client/LV2/juce_LV2_Client.cpp
  8. +0
    -170
      modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterApp.cpp
  9. +0
    -774
      modules/juce_audio_plugin_client/Unity/juce_Unity_Wrapper.cpp
  10. +0
    -2208
      modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.cpp
  11. +0
    -4281
      modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp
  12. +0
    -145
      modules/juce_audio_plugin_client/detail/juce_PluginUtilities.cpp
  13. +105
    -12
      modules/juce_audio_plugin_client/detail/juce_PluginUtilities.h
  14. +47
    -3
      modules/juce_audio_plugin_client/detail/juce_VSTWindowUtilities.h
  15. +0
    -96
      modules/juce_audio_plugin_client/detail/juce_VSTWindowUtilities.mm
  16. +2559
    -1
      modules/juce_audio_plugin_client/juce_audio_plugin_client_AAX.cpp
  17. +1
    -1
      modules/juce_audio_plugin_client/juce_audio_plugin_client_AAX.mm
  18. +1
    -1
      modules/juce_audio_plugin_client/juce_audio_plugin_client_AAX_utils.cpp
  19. +20
    -1
      modules/juce_audio_plugin_client/juce_audio_plugin_client_ARA.cpp
  20. +2595
    -1
      modules/juce_audio_plugin_client/juce_audio_plugin_client_AU_1.mm
  21. +12
    -12
      modules/juce_audio_plugin_client/juce_audio_plugin_client_AU_2.mm
  22. +1988
    -1
      modules/juce_audio_plugin_client/juce_audio_plugin_client_AUv3.mm
  23. +1790
    -1
      modules/juce_audio_plugin_client/juce_audio_plugin_client_LV2.cpp
  24. +146
    -1
      modules/juce_audio_plugin_client/juce_audio_plugin_client_Standalone.cpp
  25. +749
    -1
      modules/juce_audio_plugin_client/juce_audio_plugin_client_Unity.cpp
  26. +2183
    -1
      modules/juce_audio_plugin_client/juce_audio_plugin_client_VST2.cpp
  27. +1
    -1
      modules/juce_audio_plugin_client/juce_audio_plugin_client_VST2.mm
  28. +4256
    -1
      modules/juce_audio_plugin_client/juce_audio_plugin_client_VST3.cpp
  29. +1
    -3
      modules/juce_audio_plugin_client/juce_audio_plugin_client_VST3.mm
  30. +1
    -1
      modules/juce_events/native/juce_win32_Messaging.cpp
  31. +0
    -1
      modules/juce_gui_basics/native/juce_win32_Windowing.cpp

+ 0
- 11
extras/Build/CMake/JUCEModuleSupport.cmake View File

@@ -313,7 +313,6 @@ endfunction()

function(_juce_add_plugin_wrapper_target format path out_path)
_juce_module_sources("${path}" "${out_path}" out_var headers)
list(FILTER out_var EXCLUDE REGEX "/juce_audio_plugin_client_utils.cpp$")
set(target_name juce_audio_plugin_client_${format})

_juce_add_interface_library("${target_name}" ${out_var})
@@ -452,16 +451,6 @@ function(juce_add_module module_path)
_juce_add_plugin_wrapper_target(${kind} "${module_path}" "${base_path}")
endforeach()

set(utils_source
"${base_path}/${module_name}/juce_audio_plugin_client_utils.cpp")
add_library(juce_audio_plugin_client_utils INTERFACE)
target_sources(juce_audio_plugin_client_utils INTERFACE "${utils_source}")

if(JUCE_ARG_ALIAS_NAMESPACE)
add_library(${JUCE_ARG_ALIAS_NAMESPACE}::juce_audio_plugin_client_utils
ALIAS juce_audio_plugin_client_utils)
endif()

file(GLOB_RECURSE all_module_files
CONFIGURE_DEPENDS LIST_DIRECTORIES FALSE
RELATIVE "${module_parent_path}"


+ 1
- 1
extras/Build/CMake/JUCEUtils.cmake View File

@@ -1211,7 +1211,7 @@ endfunction()
function(_juce_configure_plugin_targets target)
_juce_set_output_name(${target} $<TARGET_PROPERTY:${target},JUCE_PRODUCT_NAME>_SharedCode)

target_link_libraries(${target} PRIVATE juce::juce_audio_plugin_client_utils)
target_link_libraries(${target} PRIVATE juce::juce_audio_plugin_client)

get_target_property(enabled_formats ${target} JUCE_FORMATS)



+ 0
- 2584
modules/juce_audio_plugin_client/AAX/juce_AAX_Wrapper.cpp
File diff suppressed because it is too large
View File


+ 0
- 45
modules/juce_audio_plugin_client/ARA/juce_ARA_Wrapper.cpp View File

@@ -1,45 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
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 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-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 <juce_core/system/juce_TargetPlatform.h>
#include <juce_audio_plugin_client/detail/juce_CheckSettingMacros.h>
#if JucePlugin_Enable_ARA
#include <juce_audio_plugin_client/detail/juce_IncludeSystemHeaders.h>
#include <juce_audio_plugin_client/detail/juce_IncludeModuleHeaders.h>
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wunused-parameter", "-Wgnu-zero-variadic-macro-arguments", "-Wmissing-prototypes")
JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4100)
#include <ARA_Library/PlugIn/ARAPlug.cpp>
#include <ARA_Library/Dispatch/ARAPlugInDispatch.cpp>
#include <ARA_Library/Utilities/ARAPitchInterpretation.cpp>
#include <ARA_Library/Utilities/ARAChannelArrangement.cpp>
JUCE_END_IGNORE_WARNINGS_MSVC
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
#endif

+ 0
- 2620
modules/juce_audio_plugin_client/AU/juce_AU_Wrapper.mm
File diff suppressed because it is too large
View File


+ 0
- 2013
modules/juce_audio_plugin_client/AU/juce_AUv3_Wrapper.mm
File diff suppressed because it is too large
View File


+ 0
- 1815
modules/juce_audio_plugin_client/LV2/juce_LV2_Client.cpp
File diff suppressed because it is too large
View File


+ 0
- 170
modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterApp.cpp View File

@@ -1,170 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
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 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-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 <juce_core/system/juce_TargetPlatform.h>
#include <juce_audio_plugin_client/detail/juce_CheckSettingMacros.h>
#include <juce_audio_plugin_client/detail/juce_IncludeSystemHeaders.h>
#include <juce_audio_plugin_client/detail/juce_IncludeModuleHeaders.h>
#include <juce_audio_plugin_client/detail/juce_WindowsHooks.h>
#include <juce_audio_devices/juce_audio_devices.h>
#include <juce_gui_extra/juce_gui_extra.h>
#include <juce_audio_utils/juce_audio_utils.h>
// You can set this flag in your build if you need to specify a different
// standalone JUCEApplication class for your app to use. If you don't
// set it then by default we'll just create a simple one as below.
#if ! JUCE_USE_CUSTOM_PLUGIN_STANDALONE_APP
#include <juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h>
namespace juce
{
//==============================================================================
class StandaloneFilterApp : public JUCEApplication
{
public:
StandaloneFilterApp()
{
PropertiesFile::Options options;
options.applicationName = getApplicationName();
options.filenameSuffix = ".settings";
options.osxLibrarySubFolder = "Application Support";
#if JUCE_LINUX || JUCE_BSD
options.folderName = "~/.config";
#else
options.folderName = "";
#endif
appProperties.setStorageParameters (options);
}
const String getApplicationName() override { return CharPointer_UTF8 (JucePlugin_Name); }
const String getApplicationVersion() override { return JucePlugin_VersionString; }
bool moreThanOneInstanceAllowed() override { return true; }
void anotherInstanceStarted (const String&) override {}
virtual StandaloneFilterWindow* createWindow()
{
#ifdef JucePlugin_PreferredChannelConfigurations
StandalonePluginHolder::PluginInOuts channels[] = { JucePlugin_PreferredChannelConfigurations };
#endif
return new StandaloneFilterWindow (getApplicationName(),
LookAndFeel::getDefaultLookAndFeel().findColour (ResizableWindow::backgroundColourId),
appProperties.getUserSettings(),
false, {}, nullptr
#ifdef JucePlugin_PreferredChannelConfigurations
, juce::Array<StandalonePluginHolder::PluginInOuts> (channels, juce::numElementsInArray (channels))
#else
, {}
#endif
#if JUCE_DONT_AUTO_OPEN_MIDI_DEVICES_ON_MOBILE
, false
#endif
);
}
//==============================================================================
void initialise (const String&) override
{
mainWindow.reset (createWindow());
#if JUCE_STANDALONE_FILTER_WINDOW_USE_KIOSK_MODE
Desktop::getInstance().setKioskModeComponent (mainWindow.get(), false);
#endif
mainWindow->setVisible (true);
}
void shutdown() override
{
mainWindow = nullptr;
appProperties.saveIfNeeded();
}
//==============================================================================
void systemRequestedQuit() override
{
if (mainWindow.get() != nullptr)
mainWindow->pluginHolder->savePluginState();
if (ModalComponentManager::getInstance()->cancelAllModalComponents())
{
Timer::callAfterDelay (100, []()
{
if (auto app = JUCEApplicationBase::getInstance())
app->systemRequestedQuit();
});
}
else
{
quit();
}
}
protected:
ApplicationProperties appProperties;
std::unique_ptr<StandaloneFilterWindow> mainWindow;
};
} // namespace juce
#if JucePlugin_Build_Standalone && JUCE_IOS
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wmissing-prototypes")
using namespace juce;
bool JUCE_CALLTYPE juce_isInterAppAudioConnected()
{
if (auto holder = StandalonePluginHolder::getInstance())
return holder->isInterAppAudioConnected();
return false;
}
void JUCE_CALLTYPE juce_switchToHostApplication()
{
if (auto holder = StandalonePluginHolder::getInstance())
holder->switchToHostApplication();
}
Image JUCE_CALLTYPE juce_getIAAHostIcon (int size)
{
if (auto holder = StandalonePluginHolder::getInstance())
return holder->getIAAHostIcon (size);
return Image();
}
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
#endif
#endif

+ 0
- 774
modules/juce_audio_plugin_client/Unity/juce_Unity_Wrapper.cpp View File

@@ -1,774 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
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 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-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 <juce_core/system/juce_TargetPlatform.h>
#if JucePlugin_Build_Unity
#include <juce_audio_plugin_client/detail/juce_PluginUtilities.h>
#include <juce_audio_processors/format_types/juce_LegacyAudioParameter.cpp>
#if JUCE_WINDOWS
#include <juce_audio_plugin_client/detail/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(); }
using ComponentPeer::localToGlobal;
using ComponentPeer::globalToLocal;
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::defaultPressure,
juce::MouseInputSource::defaultOrientation, 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)
{
}
std::unique_ptr<ImageType> createType() const override
{
return std::make_unique<SoftwareImageType>();
}
std::unique_ptr<LowLevelGraphicsContext> createLowLevelContext() override
{
return std::make_unique<LowLevelGraphicsSoftwareRenderer> (Image (this));
}
void initialiseBitmapData (Image::BitmapData& bitmap, int x, int y, [[maybe_unused]] Image::BitmapData::ReadWriteMode mode) override
{
const auto offset = (size_t) x * (size_t) pixelStride + (size_t) y * (size_t) lineStride;
bitmap.data = imageData + offset;
bitmap.size = (size_t) (lineStride * height) - offset;
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::defaultPressure, juce::MouseInputSource::defaultOrientation, 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; }
OptionalBorderSize getFrameSizeIfPresent() const override { return {}; }
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)
};
static ComponentPeer* createUnityPeer (Component& c) { return new UnityPeer (c); }
//==============================================================================
class AudioProcessorUnityWrapper
{
public:
AudioProcessorUnityWrapper (bool isTemporary)
{
pluginInstance = createPluginFilterOfType (AudioProcessor::wrapperType_Unity);
if (! isTemporary && pluginInstance->hasEditor())
{
pluginInstanceEditor.reset (pluginInstance->createEditorIfNeeded());
pluginInstanceEditor->setVisible (true);
detail::PluginUtilities::addToDesktop (*pluginInstanceEditor, nullptr);
}
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]);
jassertquiet (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)
{
// If the plugin has a bypass parameter, set it to the current bypass state
if (auto* param = pluginInstance->getBypassParameter())
if (isBypassed != (param->getValue() >= 0.5f))
param->setValueNotifyingHost (isBypassed ? 1.0f : 0.0f);
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 = (int) juceParameters.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.getParamForIndex (i);
auto& paramDef = parametersPtr.get()[i];
const auto nameLength = (size_t) numElementsInArray (paramDef.name);
const auto unitLength = (size_t) numElementsInArray (paramDef.unit);
parameter->getName ((int) nameLength - 1).copyToUTF8 (paramDef.name, nameLength);
if (parameter->getLabel().isNotEmpty())
parameter->getLabel().copyToUTF8 (paramDef.unit, unitLength);
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->getBypassParameter() == nullptr)
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)
};
//==============================================================================
static 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);
}
//==============================================================================
static UnityAudioEffectDefinition getEffectDefinition()
{
const auto wrapper = std::make_unique<AudioProcessorUnityWrapper> (true);
const String originalName { JucePlugin_Name };
const auto name = (! originalName.startsWithIgnoreCase ("audioplugin") ? "audioplugin_" : "") + originalName;
UnityAudioEffectDefinition result{};
name.copyToUTF8 (result.name, (size_t) numElementsInArray (result.name));
result.structSize = sizeof (UnityAudioEffectDefinition);
result.parameterStructSize = sizeof (UnityAudioParameterDefinition);
result.apiVersion = UNITY_AUDIO_PLUGIN_API_VERSION;
result.pluginVersion = JucePlugin_VersionCode;
// effects must set this to 0, generators > 0
result.channels = (wrapper->getNumInputChannels() != 0 ? 0
: static_cast<uint32> (wrapper->getNumOutputChannels()));
wrapper->declareParameters (result);
result.create = [] (UnityAudioEffectState* state)
{
auto* pluginInstance = new AudioProcessorUnityWrapper (false);
pluginInstance->create (state);
state->effectData = pluginInstance;
onWrapperCreation (pluginInstance);
return 0;
};
result.release = [] (UnityAudioEffectState* state)
{
auto* pluginInstance = state->getEffectData<AudioProcessorUnityWrapper>();
pluginInstance->release();
onWrapperDeletion (pluginInstance);
delete pluginInstance;
if (getWrapperMap().size() == 0)
shutdownJuce_GUI();
return 0;
};
result.reset = [] (UnityAudioEffectState* state)
{
auto* pluginInstance = state->getEffectData<AudioProcessorUnityWrapper>();
pluginInstance->reset();
return 0;
};
result.setPosition = [] (UnityAudioEffectState* state, unsigned int pos)
{
ignoreUnused (state, pos);
return 0;
};
result.process = [] (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);
const 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;
};
result.setFloatParameter = [] (UnityAudioEffectState* state, int index, float value)
{
auto* pluginInstance = state->getEffectData<AudioProcessorUnityWrapper>();
pluginInstance->setParameter (index, value);
return 0;
};
result.getFloatParameter = [] (UnityAudioEffectState* state, int index, float* value, char* valueStr)
{
auto* pluginInstance = state->getEffectData<AudioProcessorUnityWrapper>();
*value = pluginInstance->getParameter (index);
pluginInstance->getParameterString (index).copyToUTF8 (valueStr, 15);
return 0;
};
result.getFloatBuffer = [] (UnityAudioEffectState* state, const char* kind, float* buffer, int numSamples)
{
ignoreUnused (numSamples);
const StringRef kindStr { kind };
if (kindStr == StringRef ("Editor"))
{
auto* pluginInstance = state->getEffectData<AudioProcessorUnityWrapper>();
buffer[0] = pluginInstance->hasEditor() ? 1.0f : 0.0f;
}
else if (kindStr == StringRef ("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 (kindStr == StringRef ("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;
};
return result;
}
} // namespace juce
// From reading the example code, it seems that the triple indirection indicates
// an out-value of an array of pointers. That is, after calling this function, definitionsPtr
// should point to a pre-existing/static array of pointer-to-effect-definition.
UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API UnityGetAudioEffectDefinitions (UnityAudioEffectDefinition*** definitionsPtr)
{
if (juce::getWrapperMap().size() == 0)
juce::initialiseJuce_GUI();
static std::once_flag flag;
std::call_once (flag, [] { juce::juce_createUnityPeerFn = juce::createUnityPeer; });
static auto definition = juce::getEffectDefinition();
static UnityAudioEffectDefinition* definitions[] { &definition };
*definitionsPtr = definitions;
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
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wmissing-prototypes")
extern "C" BOOL WINAPI DllMain (HINSTANCE instance, DWORD reason, LPVOID)
{
if (reason == DLL_PROCESS_ATTACH)
juce::Process::setCurrentModuleInstanceHandle (instance);
return true;
}
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
#endif
#endif

+ 0
- 2208
modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.cpp
File diff suppressed because it is too large
View File


+ 0
- 4281
modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp
File diff suppressed because it is too large
View File


+ 0
- 145
modules/juce_audio_plugin_client/detail/juce_PluginUtilities.cpp View File

@@ -1,145 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
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 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-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 <juce_audio_plugin_client/detail/juce_PluginUtilities.h>
#if JUCE_WINDOWS
#include <windows.h>
#endif
namespace juce::detail
{
#if JucePlugin_Build_Unity
bool isRunningInUnity();
bool isRunningInUnity() { return PluginHostType::getPluginLoadedAs() == AudioProcessor::wrapperType_Unity; }
#endif
#if VST3_REPLACEMENT_AVAILABLE
// NB: Nasty old-fashioned code in here because it's copied from the Steinberg example code.
void PluginUtilities::getUUIDForVST2ID (bool forControllerUID, uint8 uuid[16])
{
#if JUCE_MSVC
const auto juce_sprintf = [] (auto&& head, auto&&... tail) { sprintf_s (head, numElementsInArray (head), tail...); };
const auto juce_strcpy = [] (auto&& head, auto&&... tail) { strcpy_s (head, numElementsInArray (head), tail...); };
const auto juce_strcat = [] (auto&& head, auto&&... tail) { strcat_s (head, numElementsInArray (head), tail...); };
const auto juce_sscanf = [] (auto&&... args) { sscanf_s (args...); };
#else
const auto juce_sprintf = [] (auto&& head, auto&&... tail) { snprintf (head, (size_t) numElementsInArray (head), tail...); };
const auto juce_strcpy = [] (auto&&... args) { strcpy (args...); };
const auto juce_strcat = [] (auto&&... args) { strcat (args...); };
const auto juce_sscanf = [] (auto&&... args) { sscanf (args...); };
#endif
char uidString[33];
const int vstfxid = (('V' << 16) | ('S' << 8) | (forControllerUID ? 'E' : 'T'));
char vstfxidStr[7] = { 0 };
juce_sprintf (vstfxidStr, "%06X", vstfxid);
juce_strcpy (uidString, vstfxidStr);
char uidStr[9] = { 0 };
juce_sprintf (uidStr, "%08X", JucePlugin_VSTUniqueID);
juce_strcat (uidString, uidStr);
char nameidStr[3] = { 0 };
const size_t len = strlen (JucePlugin_Name);
for (size_t i = 0; i <= 8; ++i)
{
juce::uint8 c = i < len ? static_cast<juce::uint8> (JucePlugin_Name[i]) : 0;
if (c >= 'A' && c <= 'Z')
c += 'a' - 'A';
juce_sprintf (nameidStr, "%02X", c);
juce_strcat (uidString, nameidStr);
}
unsigned long p0;
unsigned int p1, p2;
unsigned int p3[8];
juce_sscanf (uidString, "%08lX%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X",
&p0, &p1, &p2, &p3[0], &p3[1], &p3[2], &p3[3], &p3[4], &p3[5], &p3[6], &p3[7]);
union q0_u {
uint32 word;
uint8 bytes[4];
} q0;
union q1_u {
uint16 half;
uint8 bytes[2];
} q1, q2;
q0.word = static_cast<uint32> (p0);
q1.half = static_cast<uint16> (p1);
q2.half = static_cast<uint16> (p2);
// VST3 doesn't use COM compatible UUIDs on non windows platforms
#if ! JUCE_WINDOWS
q0.word = ByteOrder::swap (q0.word);
q1.half = ByteOrder::swap (q1.half);
q2.half = ByteOrder::swap (q2.half);
#endif
for (int i = 0; i < 4; ++i)
uuid[i+0] = q0.bytes[i];
for (int i = 0; i < 2; ++i)
uuid[i+4] = q1.bytes[i];
for (int i = 0; i < 2; ++i)
uuid[i+6] = q2.bytes[i];
for (int i = 0; i < 8; ++i)
uuid[i+8] = static_cast<uint8> (p3[i]);
}
#endif
#if JucePlugin_Build_VST
bool PluginUtilities::handleManufacturerSpecificVST2Opcode ([[maybe_unused]] int32 index,
[[maybe_unused]] pointer_sized_int value,
[[maybe_unused]] void* ptr,
float)
{
#if VST3_REPLACEMENT_AVAILABLE
if ((index == (int32) ByteOrder::bigEndianInt ("stCA") || index == (int32) ByteOrder::bigEndianInt ("stCa"))
&& value == (int32) ByteOrder::bigEndianInt ("FUID") && ptr != nullptr)
{
uint8 fuid[16];
getUUIDForVST2ID (false, fuid);
::memcpy (ptr, fuid, 16);
return true;
}
#endif
return false;
}
#endif
} // namespace juce

+ 105
- 12
modules/juce_audio_plugin_client/detail/juce_PluginUtilities.h View File

@@ -30,6 +30,13 @@
namespace juce::detail
{
bool isRunningInUnity();
#if JucePlugin_Build_Unity
bool isRunningInUnity() { return PluginHostType::getPluginLoadedAs() == AudioProcessor::wrapperType_Unity; }
#else
bool isRunningInUnity() { return false; }
#endif
struct PluginUtilities
{
PluginUtilities() = delete;
@@ -61,20 +68,106 @@ struct PluginUtilities
#define JUCE_VST3_CAN_REPLACE_VST2 1
#endif
#if JucePlugin_Build_VST3 && JUCE_VST3_CAN_REPLACE_VST2 && (JUCE_MAC || JUCE_WINDOWS || JUCE_LINUX || JUCE_BSD)
#define VST3_REPLACEMENT_AVAILABLE 1
static void getUUIDForVST2ID (bool forControllerUID, uint8 uuid[16]);
#else
#define VST3_REPLACEMENT_AVAILABLE 0
#endif
// NB: Nasty old-fashioned code in here because it's copied from the Steinberg example code.
static void getUUIDForVST2ID (bool forControllerUID, uint8 uuid[16])
{
#if JUCE_WINDOWS && ! JUCE_MINGW
const auto juce_sprintf = [] (auto&& head, auto&&... tail) { sprintf_s (head, (size_t) numElementsInArray (head), tail...); };
const auto juce_strcpy = [] (auto&& head, auto&&... tail) { strcpy_s (head, (size_t) numElementsInArray (head), tail...); };
const auto juce_strcat = [] (auto&& head, auto&&... tail) { strcat_s (head, (size_t) numElementsInArray (head), tail...); };
const auto juce_sscanf = [] (auto&&... args) { sscanf_s (args...); };
#else
const auto juce_sprintf = [] (auto&& head, auto&&... tail) { snprintf (head, (size_t) numElementsInArray (head), tail...); };
const auto juce_strcpy = [] (auto&&... args) { strcpy (args...); };
const auto juce_strcat = [] (auto&&... args) { strcat (args...); };
const auto juce_sscanf = [] (auto&&... args) { sscanf (args...); };
#endif
char uidString[33];
const int vstfxid = (('V' << 16) | ('S' << 8) | (forControllerUID ? 'E' : 'T'));
char vstfxidStr[7] = { 0 };
juce_sprintf (vstfxidStr, "%06X", vstfxid);
juce_strcpy (uidString, vstfxidStr);
char uidStr[9] = { 0 };
juce_sprintf (uidStr, "%08X", JucePlugin_VSTUniqueID);
juce_strcat (uidString, uidStr);
char nameidStr[3] = { 0 };
const size_t len = strlen (JucePlugin_Name);
for (size_t i = 0; i <= 8; ++i)
{
juce::uint8 c = i < len ? static_cast<juce::uint8> (JucePlugin_Name[i]) : 0;
if (c >= 'A' && c <= 'Z')
c += 'a' - 'A';
juce_sprintf (nameidStr, "%02X", c);
juce_strcat (uidString, nameidStr);
}
unsigned long p0;
unsigned int p1, p2;
unsigned int p3[8];
juce_sscanf (uidString, "%08lX%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X",
&p0, &p1, &p2, &p3[0], &p3[1], &p3[2], &p3[3], &p3[4], &p3[5], &p3[6], &p3[7]);
union q0_u {
uint32 word;
uint8 bytes[4];
} q0;
union q1_u {
uint16 half;
uint8 bytes[2];
} q1, q2;
q0.word = static_cast<uint32> (p0);
q1.half = static_cast<uint16> (p1);
q2.half = static_cast<uint16> (p2);
// VST3 doesn't use COM compatible UUIDs on non windows platforms
#if ! JUCE_WINDOWS
q0.word = ByteOrder::swap (q0.word);
q1.half = ByteOrder::swap (q1.half);
q2.half = ByteOrder::swap (q2.half);
#endif
for (int i = 0; i < 4; ++i)
uuid[i+0] = q0.bytes[i];
for (int i = 0; i < 2; ++i)
uuid[i+4] = q1.bytes[i];
for (int i = 0; i < 2; ++i)
uuid[i+6] = q2.bytes[i];
for (int i = 0; i < 8; ++i)
uuid[i+8] = static_cast<uint8> (p3[i]);
}
#if JucePlugin_Build_VST
static bool handleManufacturerSpecificVST2Opcode (int32 index,
pointer_sized_int value,
void* ptr,
float);
static bool handleManufacturerSpecificVST2Opcode ([[maybe_unused]] int32 index,
[[maybe_unused]] pointer_sized_int value,
[[maybe_unused]] void* ptr,
float)
{
#if JUCE_VST3_CAN_REPLACE_VST2
if ((index == (int32) ByteOrder::bigEndianInt ("stCA") || index == (int32) ByteOrder::bigEndianInt ("stCa"))
&& value == (int32) ByteOrder::bigEndianInt ("FUID") && ptr != nullptr)
{
uint8 fuid[16];
getUUIDForVST2ID (false, fuid);
::memcpy (ptr, fuid, 16);
return true;
}
#endif
return false;
}
#endif
};


+ 47
- 3
modules/juce_audio_plugin_client/detail/juce_VSTWindowUtilities.h View File

@@ -38,15 +38,59 @@ struct VSTWindowUtilities
static void* attachComponentToWindowRefVST (Component* comp,
int desktopFlags,
void* parentWindowOrView);
void* parentWindowOrView)
{
JUCE_AUTORELEASEPOOL
{
NSView* parentView = [(NSView*) parentWindowOrView retain];
const auto defaultFlags = JucePlugin_EditorRequiresKeyboardFocus
? 0
: ComponentPeer::windowIgnoresKeyPresses;
comp->addToDesktop (desktopFlags | defaultFlags, parentView);
// (this workaround is because Wavelab provides a zero-size parent view..)
if ([parentView frame].size.height == 0)
[((NSView*) comp->getWindowHandle()) setFrameOrigin: NSZeroPoint];
comp->setVisible (true);
comp->toFront (false);
[[parentView window] setAcceptsMouseMovedEvents: YES];
return parentView;
}
}
static void detachComponentFromWindowRefVST (Component* comp,
void* window);
void* window)
{
JUCE_AUTORELEASEPOOL
{
comp->removeFromDesktop();
[(id) window release];
}
}
static void setNativeHostWindowSizeVST (void* window,
Component* component,
int newWidth,
int newHeight);
int newHeight)
{
JUCE_AUTORELEASEPOOL
{
if (NSView* hostView = (NSView*) window)
{
const int dx = newWidth - component->getWidth();
const int dy = newHeight - component->getHeight();
NSRect r = [hostView frame];
r.size.width += dx;
r.size.height += dy;
r.origin.y -= dy;
[hostView setFrame: r];
}
}
}
};
} // namespace juce::detail


+ 0
- 96
modules/juce_audio_plugin_client/detail/juce_VSTWindowUtilities.mm View File

@@ -1,96 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
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 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-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
#include <juce_core/system/juce_TargetPlatform.h>
#if JUCE_MAC
#include <juce_audio_plugin_client/detail/juce_CheckSettingMacros.h>
#include <juce_audio_plugin_client/detail/juce_IncludeSystemHeaders.h>
#include <juce_audio_plugin_client/detail/juce_VSTWindowUtilities.h>
namespace juce::detail
{
void* VSTWindowUtilities::attachComponentToWindowRefVST (Component* comp,
int desktopFlags,
void* parentWindowOrView)
{
JUCE_AUTORELEASEPOOL
{
NSView* parentView = [(NSView*) parentWindowOrView retain];
const auto defaultFlags = JucePlugin_EditorRequiresKeyboardFocus
? 0
: ComponentPeer::windowIgnoresKeyPresses;
comp->addToDesktop (desktopFlags | defaultFlags, parentView);
// (this workaround is because Wavelab provides a zero-size parent view..)
if ([parentView frame].size.height == 0)
[((NSView*) comp->getWindowHandle()) setFrameOrigin: NSZeroPoint];
comp->setVisible (true);
comp->toFront (false);
[[parentView window] setAcceptsMouseMovedEvents: YES];
return parentView;
}
}
void VSTWindowUtilities::detachComponentFromWindowRefVST (Component* comp, void* window)
{
JUCE_AUTORELEASEPOOL
{
comp->removeFromDesktop();
[(id) window release];
}
}
void VSTWindowUtilities::setNativeHostWindowSizeVST (void* window,
Component* component,
int newWidth,
int newHeight)
{
JUCE_AUTORELEASEPOOL
{
if (NSView* hostView = (NSView*) window)
{
const int dx = newWidth - component->getWidth();
const int dy = newHeight - component->getHeight();
NSRect r = [hostView frame];
r.size.width += dx;
r.size.height += dy;
r.origin.y -= dy;
[hostView setFrame: r];
}
}
}
} // namespace juce::detail
#endif

+ 2559
- 1
modules/juce_audio_plugin_client/juce_audio_plugin_client_AAX.cpp
File diff suppressed because it is too large
View File


+ 1
- 1
modules/juce_audio_plugin_client/juce_audio_plugin_client_AAX.mm View File

@@ -24,4 +24,4 @@
*/
#define JUCE_INCLUDED_AAX_IN_MM 1
#include "AAX/juce_AAX_Wrapper.cpp"
#include "juce_audio_plugin_client_AAX.cpp"

+ 1
- 1
modules/juce_audio_plugin_client/juce_audio_plugin_client_AAX_utils.cpp View File

@@ -25,7 +25,7 @@
#include <juce_core/system/juce_TargetPlatform.h>
#if JucePlugin_Build_AAX && (JUCE_MAC || JUCE_WINDOWS)
#if JucePlugin_Build_AAX
#include <AAX_Version.h>


+ 20
- 1
modules/juce_audio_plugin_client/juce_audio_plugin_client_ARA.cpp View File

@@ -23,4 +23,23 @@
==============================================================================
*/
#include "ARA/juce_ARA_Wrapper.cpp"
#include <juce_core/system/juce_TargetPlatform.h>
#include <juce_audio_plugin_client/detail/juce_CheckSettingMacros.h>
#if JucePlugin_Enable_ARA
#include <juce_audio_plugin_client/detail/juce_IncludeSystemHeaders.h>
#include <juce_audio_plugin_client/detail/juce_IncludeModuleHeaders.h>
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wunused-parameter", "-Wgnu-zero-variadic-macro-arguments", "-Wmissing-prototypes")
JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4100)
#include <ARA_Library/PlugIn/ARAPlug.cpp>
#include <ARA_Library/Dispatch/ARAPlugInDispatch.cpp>
#include <ARA_Library/Utilities/ARAPitchInterpretation.cpp>
#include <ARA_Library/Utilities/ARAChannelArrangement.cpp>
JUCE_END_IGNORE_WARNINGS_MSVC
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
#endif

+ 2595
- 1
modules/juce_audio_plugin_client/juce_audio_plugin_client_AU_1.mm
File diff suppressed because it is too large
View File


+ 12
- 12
modules/juce_audio_plugin_client/juce_audio_plugin_client_AU_2.mm View File

@@ -86,18 +86,18 @@ enum MIDICVStatus : unsigned int
#endif
#include "AU/AudioUnitSDK/AUBase.cpp"
#include "AU/AudioUnitSDK/AUBuffer.cpp"
#include "AU/AudioUnitSDK/AUBufferAllocator.cpp"
#include "AU/AudioUnitSDK/AUEffectBase.cpp"
#include "AU/AudioUnitSDK/AUInputElement.cpp"
#include "AU/AudioUnitSDK/AUMIDIBase.cpp"
#include "AU/AudioUnitSDK/AUMIDIEffectBase.cpp"
#include "AU/AudioUnitSDK/AUOutputElement.cpp"
#include "AU/AudioUnitSDK/AUPlugInDispatch.cpp"
#include "AU/AudioUnitSDK/AUScopeElement.cpp"
#include "AU/AudioUnitSDK/ComponentBase.cpp"
#include "AU/AudioUnitSDK/MusicDeviceBase.cpp"
#include <juce_audio_plugin_client/AU/AudioUnitSDK/AUBase.cpp>
#include <juce_audio_plugin_client/AU/AudioUnitSDK/AUBuffer.cpp>
#include <juce_audio_plugin_client/AU/AudioUnitSDK/AUBufferAllocator.cpp>
#include <juce_audio_plugin_client/AU/AudioUnitSDK/AUEffectBase.cpp>
#include <juce_audio_plugin_client/AU/AudioUnitSDK/AUInputElement.cpp>
#include <juce_audio_plugin_client/AU/AudioUnitSDK/AUMIDIBase.cpp>
#include <juce_audio_plugin_client/AU/AudioUnitSDK/AUMIDIEffectBase.cpp>
#include <juce_audio_plugin_client/AU/AudioUnitSDK/AUOutputElement.cpp>
#include <juce_audio_plugin_client/AU/AudioUnitSDK/AUPlugInDispatch.cpp>
#include <juce_audio_plugin_client/AU/AudioUnitSDK/AUScopeElement.cpp>
#include <juce_audio_plugin_client/AU/AudioUnitSDK/ComponentBase.cpp>
#include <juce_audio_plugin_client/AU/AudioUnitSDK/MusicDeviceBase.cpp>
#undef verify
#undef verify_noerr


+ 1988
- 1
modules/juce_audio_plugin_client/juce_audio_plugin_client_AUv3.mm
File diff suppressed because it is too large
View File


+ 1790
- 1
modules/juce_audio_plugin_client/juce_audio_plugin_client_LV2.cpp
File diff suppressed because it is too large
View File


+ 146
- 1
modules/juce_audio_plugin_client/juce_audio_plugin_client_Standalone.cpp View File

@@ -31,7 +31,152 @@
#error To compile AudioUnitv3 and/or Standalone plug-ins, you need to add the juce_audio_utils and juce_audio_devices modules!
#endif
#include "Standalone/juce_StandaloneFilterApp.cpp"
#include <juce_core/system/juce_TargetPlatform.h>
#include <juce_audio_plugin_client/detail/juce_CheckSettingMacros.h>
#include <juce_audio_plugin_client/detail/juce_IncludeSystemHeaders.h>
#include <juce_audio_plugin_client/detail/juce_IncludeModuleHeaders.h>
#include <juce_audio_plugin_client/detail/juce_WindowsHooks.h>
#include <juce_audio_plugin_client/detail/juce_PluginUtilities.h>
#include <juce_audio_devices/juce_audio_devices.h>
#include <juce_gui_extra/juce_gui_extra.h>
#include <juce_audio_utils/juce_audio_utils.h>
// You can set this flag in your build if you need to specify a different
// standalone JUCEApplication class for your app to use. If you don't
// set it then by default we'll just create a simple one as below.
#if ! JUCE_USE_CUSTOM_PLUGIN_STANDALONE_APP
#include <juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h>
namespace juce
{
//==============================================================================
class StandaloneFilterApp : public JUCEApplication
{
public:
StandaloneFilterApp()
{
PropertiesFile::Options options;
options.applicationName = getApplicationName();
options.filenameSuffix = ".settings";
options.osxLibrarySubFolder = "Application Support";
#if JUCE_LINUX || JUCE_BSD
options.folderName = "~/.config";
#else
options.folderName = "";
#endif
appProperties.setStorageParameters (options);
}
const String getApplicationName() override { return CharPointer_UTF8 (JucePlugin_Name); }
const String getApplicationVersion() override { return JucePlugin_VersionString; }
bool moreThanOneInstanceAllowed() override { return true; }
void anotherInstanceStarted (const String&) override {}
virtual StandaloneFilterWindow* createWindow()
{
#ifdef JucePlugin_PreferredChannelConfigurations
StandalonePluginHolder::PluginInOuts channels[] = { JucePlugin_PreferredChannelConfigurations };
#endif
return new StandaloneFilterWindow (getApplicationName(),
LookAndFeel::getDefaultLookAndFeel().findColour (ResizableWindow::backgroundColourId),
appProperties.getUserSettings(),
false, {}, nullptr
#ifdef JucePlugin_PreferredChannelConfigurations
, juce::Array<StandalonePluginHolder::PluginInOuts> (channels, juce::numElementsInArray (channels))
#else
, {}
#endif
#if JUCE_DONT_AUTO_OPEN_MIDI_DEVICES_ON_MOBILE
, false
#endif
);
}
//==============================================================================
void initialise (const String&) override
{
mainWindow.reset (createWindow());
#if JUCE_STANDALONE_FILTER_WINDOW_USE_KIOSK_MODE
Desktop::getInstance().setKioskModeComponent (mainWindow.get(), false);
#endif
mainWindow->setVisible (true);
}
void shutdown() override
{
mainWindow = nullptr;
appProperties.saveIfNeeded();
}
//==============================================================================
void systemRequestedQuit() override
{
if (mainWindow.get() != nullptr)
mainWindow->pluginHolder->savePluginState();
if (ModalComponentManager::getInstance()->cancelAllModalComponents())
{
Timer::callAfterDelay (100, []()
{
if (auto app = JUCEApplicationBase::getInstance())
app->systemRequestedQuit();
});
}
else
{
quit();
}
}
protected:
ApplicationProperties appProperties;
std::unique_ptr<StandaloneFilterWindow> mainWindow;
};
} // namespace juce
#if JucePlugin_Build_Standalone && JUCE_IOS
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wmissing-prototypes")
using namespace juce;
bool JUCE_CALLTYPE juce_isInterAppAudioConnected()
{
if (auto holder = StandalonePluginHolder::getInstance())
return holder->isInterAppAudioConnected();
return false;
}
void JUCE_CALLTYPE juce_switchToHostApplication()
{
if (auto holder = StandalonePluginHolder::getInstance())
holder->switchToHostApplication();
}
Image JUCE_CALLTYPE juce_getIAAHostIcon (int size)
{
if (auto holder = StandalonePluginHolder::getInstance())
return holder->getIAAHostIcon (size);
return Image();
}
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
#endif
#endif
#if JUCE_USE_CUSTOM_PLUGIN_STANDALONE_APP
extern juce::JUCEApplicationBase* juce_CreateApplication();


+ 749
- 1
modules/juce_audio_plugin_client/juce_audio_plugin_client_Unity.cpp View File

@@ -23,4 +23,752 @@
==============================================================================
*/
#include "Unity/juce_Unity_Wrapper.cpp"
#include <juce_core/system/juce_TargetPlatform.h>
#if JucePlugin_Build_Unity
#include <juce_audio_plugin_client/detail/juce_PluginUtilities.h>
#include <juce_audio_processors/format_types/juce_LegacyAudioParameter.cpp>
#if JUCE_WINDOWS
#include <juce_audio_plugin_client/detail/juce_IncludeSystemHeaders.h>
#endif
#include <juce_audio_plugin_client/Unity/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(); }
using ComponentPeer::localToGlobal;
using ComponentPeer::globalToLocal;
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::defaultPressure,
juce::MouseInputSource::defaultOrientation, 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)
{
}
std::unique_ptr<ImageType> createType() const override
{
return std::make_unique<SoftwareImageType>();
}
std::unique_ptr<LowLevelGraphicsContext> createLowLevelContext() override
{
return std::make_unique<LowLevelGraphicsSoftwareRenderer> (Image (this));
}
void initialiseBitmapData (Image::BitmapData& bitmap, int x, int y, [[maybe_unused]] Image::BitmapData::ReadWriteMode mode) override
{
const auto offset = (size_t) x * (size_t) pixelStride + (size_t) y * (size_t) lineStride;
bitmap.data = imageData + offset;
bitmap.size = (size_t) (lineStride * height) - offset;
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::defaultPressure, juce::MouseInputSource::defaultOrientation, 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; }
OptionalBorderSize getFrameSizeIfPresent() const override { return {}; }
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)
};
static ComponentPeer* createUnityPeer (Component& c) { return new UnityPeer (c); }
//==============================================================================
class AudioProcessorUnityWrapper
{
public:
AudioProcessorUnityWrapper (bool isTemporary)
{
pluginInstance = createPluginFilterOfType (AudioProcessor::wrapperType_Unity);
if (! isTemporary && pluginInstance->hasEditor())
{
pluginInstanceEditor.reset (pluginInstance->createEditorIfNeeded());
pluginInstanceEditor->setVisible (true);
detail::PluginUtilities::addToDesktop (*pluginInstanceEditor, nullptr);
}
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]);
jassertquiet (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)
{
// If the plugin has a bypass parameter, set it to the current bypass state
if (auto* param = pluginInstance->getBypassParameter())
if (isBypassed != (param->getValue() >= 0.5f))
param->setValueNotifyingHost (isBypassed ? 1.0f : 0.0f);
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 = (int) juceParameters.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.getParamForIndex (i);
auto& paramDef = parametersPtr.get()[i];
const auto nameLength = (size_t) numElementsInArray (paramDef.name);
const auto unitLength = (size_t) numElementsInArray (paramDef.unit);
parameter->getName ((int) nameLength - 1).copyToUTF8 (paramDef.name, nameLength);
if (parameter->getLabel().isNotEmpty())
parameter->getLabel().copyToUTF8 (paramDef.unit, unitLength);
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->getBypassParameter() == nullptr)
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)
};
//==============================================================================
static 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);
}
//==============================================================================
static UnityAudioEffectDefinition getEffectDefinition()
{
const auto wrapper = std::make_unique<AudioProcessorUnityWrapper> (true);
const String originalName { JucePlugin_Name };
const auto name = (! originalName.startsWithIgnoreCase ("audioplugin") ? "audioplugin_" : "") + originalName;
UnityAudioEffectDefinition result{};
name.copyToUTF8 (result.name, (size_t) numElementsInArray (result.name));
result.structSize = sizeof (UnityAudioEffectDefinition);
result.parameterStructSize = sizeof (UnityAudioParameterDefinition);
result.apiVersion = UNITY_AUDIO_PLUGIN_API_VERSION;
result.pluginVersion = JucePlugin_VersionCode;
// effects must set this to 0, generators > 0
result.channels = (wrapper->getNumInputChannels() != 0 ? 0
: static_cast<uint32> (wrapper->getNumOutputChannels()));
wrapper->declareParameters (result);
result.create = [] (UnityAudioEffectState* state)
{
auto* pluginInstance = new AudioProcessorUnityWrapper (false);
pluginInstance->create (state);
state->effectData = pluginInstance;
onWrapperCreation (pluginInstance);
return 0;
};
result.release = [] (UnityAudioEffectState* state)
{
auto* pluginInstance = state->getEffectData<AudioProcessorUnityWrapper>();
pluginInstance->release();
onWrapperDeletion (pluginInstance);
delete pluginInstance;
if (getWrapperMap().size() == 0)
shutdownJuce_GUI();
return 0;
};
result.reset = [] (UnityAudioEffectState* state)
{
auto* pluginInstance = state->getEffectData<AudioProcessorUnityWrapper>();
pluginInstance->reset();
return 0;
};
result.setPosition = [] (UnityAudioEffectState* state, unsigned int pos)
{
ignoreUnused (state, pos);
return 0;
};
result.process = [] (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);
const 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;
};
result.setFloatParameter = [] (UnityAudioEffectState* state, int index, float value)
{
auto* pluginInstance = state->getEffectData<AudioProcessorUnityWrapper>();
pluginInstance->setParameter (index, value);
return 0;
};
result.getFloatParameter = [] (UnityAudioEffectState* state, int index, float* value, char* valueStr)
{
auto* pluginInstance = state->getEffectData<AudioProcessorUnityWrapper>();
*value = pluginInstance->getParameter (index);
pluginInstance->getParameterString (index).copyToUTF8 (valueStr, 15);
return 0;
};
result.getFloatBuffer = [] (UnityAudioEffectState* state, const char* kind, float* buffer, int numSamples)
{
ignoreUnused (numSamples);
const StringRef kindStr { kind };
if (kindStr == StringRef ("Editor"))
{
auto* pluginInstance = state->getEffectData<AudioProcessorUnityWrapper>();
buffer[0] = pluginInstance->hasEditor() ? 1.0f : 0.0f;
}
else if (kindStr == StringRef ("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 (kindStr == StringRef ("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;
};
return result;
}
} // namespace juce
// From reading the example code, it seems that the triple indirection indicates
// an out-value of an array of pointers. That is, after calling this function, definitionsPtr
// should point to a pre-existing/static array of pointer-to-effect-definition.
UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API UnityGetAudioEffectDefinitions (UnityAudioEffectDefinition*** definitionsPtr)
{
if (juce::getWrapperMap().size() == 0)
juce::initialiseJuce_GUI();
static std::once_flag flag;
std::call_once (flag, [] { juce::juce_createUnityPeerFn = juce::createUnityPeer; });
static auto definition = juce::getEffectDefinition();
static UnityAudioEffectDefinition* definitions[] { &definition };
*definitionsPtr = definitions;
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
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wmissing-prototypes")
extern "C" BOOL WINAPI DllMain (HINSTANCE instance, DWORD reason, LPVOID)
{
if (reason == DLL_PROCESS_ATTACH)
juce::Process::setCurrentModuleInstanceHandle (instance);
return true;
}
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
#endif
#endif

+ 2183
- 1
modules/juce_audio_plugin_client/juce_audio_plugin_client_VST2.cpp
File diff suppressed because it is too large
View File


modules/juce_audio_plugin_client/juce_audio_plugin_client_utils.cpp → modules/juce_audio_plugin_client/juce_audio_plugin_client_VST2.mm View File

@@ -23,4 +23,4 @@
==============================================================================
*/
#include "detail/juce_PluginUtilities.cpp"
#include "juce_audio_plugin_client_VST2.cpp"

+ 4256
- 1
modules/juce_audio_plugin_client/juce_audio_plugin_client_VST3.cpp
File diff suppressed because it is too large
View File


modules/juce_audio_plugin_client/juce_audio_plugin_client_VST_utils.mm → modules/juce_audio_plugin_client/juce_audio_plugin_client_VST3.mm View File

@@ -23,6 +23,4 @@
==============================================================================
*/
#if JucePlugin_Build_VST || JucePlugin_Build_VST3
#include "detail/juce_VSTWindowUtilities.mm"
#endif
#include "juce_audio_plugin_client_VST3.cpp"

+ 1
- 1
modules/juce_events/native/juce_win32_Messaging.cpp View File

@@ -27,7 +27,7 @@ extern HWND juce_messageWindowHandle;
namespace detail
{
#if JUCE_MODULE_AVAILABLE_juce_audio_plugin_client && JucePlugin_Build_Unity
#if JUCE_MODULE_AVAILABLE_juce_audio_plugin_client
bool isRunningInUnity();
#else
constexpr bool isRunningInUnity() { return false; }


+ 0
- 1
modules/juce_gui_basics/native/juce_win32_Windowing.cpp View File

@@ -50,7 +50,6 @@ JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wcast-function-type")
#endif
void juce_repeatLastProcessPriority();
bool juce_isRunningInWine();
using CheckEventBlockedByModalComps = bool (*) (const MSG&);
extern CheckEventBlockedByModalComps isEventBlockedByModalComps;


Loading…
Cancel
Save