| @@ -4,6 +4,57 @@ JUCE breaking changes | |||
| Develop | |||
| ======= | |||
| Change | |||
| ------ | |||
| Calling AudioProcessorEditor::setResizeLimits() will no longer implicitly add a | |||
| ResizableCornerComponent to the editor if it has not already been set as | |||
| resizable. | |||
| Possible Issues | |||
| --------------- | |||
| Code which previously relied on calling this method to set up the corner | |||
| resizer will no longer work. | |||
| Workaround | |||
| ---------- | |||
| Explicitly call AudioProcessorEditor::setResizable() with the second argument | |||
| set to true to enable the corner resizer. | |||
| Rationale | |||
| --------- | |||
| The previous behaviour was undocumented and potentially confusing. There is now | |||
| a single method to control the behaviour of the editor's corner resizer to | |||
| avoid any ambiguity. | |||
| Change | |||
| ------ | |||
| The implementations of `getValue` and `setValue` in `AUInstanceParameter` now | |||
| properly take the ranges of discrete parameters into account. | |||
| Possible Issues | |||
| --------------- | |||
| This issue affects JUCE Audio Unit hosts. Automation data previously saved for | |||
| a discrete parameter with a non-zero minimum value may not set the parameter to | |||
| the same values as previous JUCE versions. Note that previously, `getValue` on | |||
| a hosted discrete parameter may have returned out-of-range values, and | |||
| `setValue` may have only mapped to a portion of the parameter range. As a | |||
| result, automation recorded for affected parameters was likely already behaving | |||
| unexpectedly. | |||
| Workaround | |||
| ---------- | |||
| There is no workaround. | |||
| Rationale | |||
| --------- | |||
| The old behaviour was incorrect, and was causing issues in plugin validators | |||
| and other hosts. Hosts expect `getValue` to return a normalised parameter | |||
| value. If this function returns an out-of-range value (including Inf and NaN) | |||
| this is likely to break assumptions made by the host, leading to crashes, | |||
| corrupted project data, or other defects. | |||
| Change | |||
| ------ | |||
| AudioProcessorListener::audioProcessorChanged gained a new parameter describing | |||
| @@ -402,6 +402,7 @@ private: | |||
| // set resize limits for this plug-in | |||
| setResizeLimits (400, 200, 1024, 700); | |||
| setResizable (true, true); | |||
| lastUIWidth .referTo (owner.state.state.getChildWithName ("uiState").getPropertyAsValue ("width", nullptr)); | |||
| lastUIHeight.referTo (owner.state.state.getChildWithName ("uiState").getPropertyAsValue ("height", nullptr)); | |||
| @@ -418,26 +418,13 @@ function(_juce_add_au_resource_fork shared_code_target au_target) | |||
| DEPENDS "${defs_file}" | |||
| VERBATIM) | |||
| execute_process(COMMAND xcode-select -p | |||
| OUTPUT_VARIABLE xcode_developer_path | |||
| RESULT_VARIABLE result_variable) | |||
| if(result_variable) | |||
| message(FATAL_ERROR | |||
| "Failed to locate an active developer directory. " | |||
| "Run 'xcode-select -s <path to Xcode>' before reconfiguring.") | |||
| endif() | |||
| string(STRIP "${xcode_developer_path}" xcode_developer_path) | |||
| add_custom_command(OUTPUT "${au_rez_output}" | |||
| COMMAND "${JUCE_XCRUN}" Rez | |||
| -d "ppc_$ppc" -d "i386_$i386" -d "ppc64_$ppc64" -d "x86_64_$x86_64" | |||
| -I "${secret_au_resource_dir}" | |||
| -I "/System/Library/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Versions/A/Headers" | |||
| -I "${xcode_developer_path}/Extras/CoreAudio/AudioUnits/AUPublic/AUBase" | |||
| -I "${xcode_developer_path}/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/AudioUnit.framework/Headers" | |||
| -isysroot "${xcode_developer_path}/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk" | |||
| -I "${CMAKE_OSX_SYSROOT}/System/Library/Frameworks/AudioUnit.framework/Headers" | |||
| -isysroot "${CMAKE_OSX_SYSROOT}" | |||
| "${au_rez_sources}" | |||
| -useDF | |||
| -o "${au_rez_output}" | |||
| @@ -463,6 +463,8 @@ AudioChannelSet AudioChannelSet::hexagonal() { return AudioChannelSet | |||
| AudioChannelSet AudioChannelSet::octagonal() { return AudioChannelSet ((1u << left) | (1u << right) | (1u << centre) | (1u << leftSurround) | (1u << rightSurround) | (1u << centreSurround) | (1u << wideLeft) | (1u << wideRight)); } | |||
| AudioChannelSet AudioChannelSet::create7point0point2() { return AudioChannelSet ((1u << left) | (1u << right) | (1u << centre) | (1u << leftSurroundSide) | (1u << rightSurroundSide) | (1u << leftSurroundRear) | (1u << rightSurroundRear) | (1u << topSideLeft) | (1u << topSideRight)); } | |||
| AudioChannelSet AudioChannelSet::create7point1point2() { return AudioChannelSet ((1u << left) | (1u << right) | (1u << centre) | (1u << LFE) | (1u << leftSurroundSide) | (1u << rightSurroundSide) | (1u << leftSurroundRear) | (1u << rightSurroundRear) | (1u << topSideLeft) | (1u << topSideRight)); } | |||
| AudioChannelSet AudioChannelSet::create7point0point4() { return AudioChannelSet ((1u << left) | (1u << right) | (1u << centre) | (1u << leftSurroundSide) | (1u << rightSurroundSide) | (1u << leftSurroundRear) | (1u << rightSurroundRear) | (1u << topFrontLeft) | (1u << topFrontRight) | (1u << topRearLeft) | (1u << topRearRight)); } | |||
| AudioChannelSet AudioChannelSet::create7point1point4() { return AudioChannelSet ((1u << left) | (1u << right) | (1u << centre) | (1u << LFE) | (1u << leftSurroundSide) | (1u << rightSurroundSide) | (1u << leftSurroundRear) | (1u << rightSurroundRear) | (1u << topFrontLeft) | (1u << topFrontRight) | (1u << topRearLeft) | (1u << topRearRight)); } | |||
| AudioChannelSet AudioChannelSet::ambisonic (int order) | |||
| { | |||
| @@ -208,6 +208,18 @@ public: | |||
| */ | |||
| static AudioChannelSet JUCE_CALLTYPE create7point1point2(); | |||
| /** Creates a set for Dolby Atmos 7.0.4 surround setup (left, right, centre, leftSurroundSide, rightSurroundSide, leftSurroundRear, rightSurroundRear, topFrontLeft, topFrontRight, topRearLeft, topRearRight). | |||
| Is equivalent to: n/a (VST), n/a (AAX), n/a (CoreAudio) | |||
| */ | |||
| static AudioChannelSet JUCE_CALLTYPE create7point0point4(); | |||
| /** Creates a set for Dolby Atmos 7.1.4 surround setup (left, right, centre, leftSurroundSide, rightSurroundSide, leftSurroundRear, rightSurroundRear, LFE, topFrontLeft, topFrontRight, topRearLeft, topRearRight). | |||
| Is equivalent to: k71_4 (VST), n/a (AAX), n/a (CoreAudio) | |||
| */ | |||
| static AudioChannelSet JUCE_CALLTYPE create7point1point4(); | |||
| //============================================================================== | |||
| /** Creates a set for quadraphonic surround setup (left, right, leftSurround, rightSurround) | |||
| @@ -44,13 +44,20 @@ void MemoryAudioSource::releaseResources() {} | |||
| void MemoryAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill) | |||
| { | |||
| if (buffer.getNumSamples() == 0) | |||
| { | |||
| bufferToFill.clearActiveBufferRegion(); | |||
| return; | |||
| } | |||
| auto& dst = *bufferToFill.buffer; | |||
| auto channels = jmin (dst.getNumChannels(), buffer.getNumChannels()); | |||
| auto max = 0, pos = 0; | |||
| auto n = buffer.getNumSamples(), m = bufferToFill.numSamples; | |||
| int max = 0, pos = 0; | |||
| auto n = buffer.getNumSamples(); | |||
| auto m = bufferToFill.numSamples; | |||
| int i; | |||
| for (i = position; (i < n || isCurrentlyLooping) && (pos < m); i += max) | |||
| int i = position; | |||
| for (; (i < n || isCurrentlyLooping) && (pos < m); i += max) | |||
| { | |||
| max = jmin (m - pos, n - (i % n)); | |||
| @@ -67,7 +74,7 @@ void MemoryAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& bufferT | |||
| if (pos < m) | |||
| dst.clear (bufferToFill.startSample + pos, m - pos); | |||
| position = (i % n); | |||
| position = i; | |||
| } | |||
| //============================================================================== | |||
| @@ -97,4 +104,158 @@ void MemoryAudioSource::setLooping (bool shouldLoop) | |||
| isCurrentlyLooping = shouldLoop; | |||
| } | |||
| //============================================================================== | |||
| //============================================================================== | |||
| #if JUCE_UNIT_TESTS | |||
| static bool operator== (const AudioBuffer<float>& a, const AudioBuffer<float>& b) | |||
| { | |||
| if (a.getNumChannels() != b.getNumChannels()) | |||
| return false; | |||
| for (int channel = 0; channel < a.getNumChannels(); ++channel) | |||
| { | |||
| auto* aPtr = a.getReadPointer (channel); | |||
| auto* bPtr = b.getReadPointer (channel); | |||
| if (std::vector<float> (aPtr, aPtr + a.getNumSamples()) | |||
| != std::vector<float> (bPtr, bPtr + b.getNumSamples())) | |||
| { | |||
| return false; | |||
| } | |||
| } | |||
| return true; | |||
| } | |||
| struct MemoryAudioSourceTests : public UnitTest | |||
| { | |||
| MemoryAudioSourceTests() : UnitTest ("MemoryAudioSource", UnitTestCategories::audio) {} | |||
| void runTest() override | |||
| { | |||
| constexpr int blockSize = 512; | |||
| AudioBuffer<float> bufferToFill { 2, blockSize }; | |||
| AudioSourceChannelInfo channelInfo { bufferToFill }; | |||
| beginTest ("A zero-length buffer produces silence, whether or not looping is enabled"); | |||
| { | |||
| for (const bool enableLooping : { false, true }) | |||
| { | |||
| AudioBuffer<float> buffer; | |||
| MemoryAudioSource source { buffer, true, false }; | |||
| source.setLooping (enableLooping); | |||
| source.prepareToPlay (blockSize, 44100.0); | |||
| for (int i = 0; i < 2; ++i) | |||
| { | |||
| play (source, channelInfo); | |||
| expect (isSilent (bufferToFill)); | |||
| } | |||
| } | |||
| } | |||
| beginTest ("A short buffer without looping is played once and followed by silence"); | |||
| { | |||
| auto buffer = getShortBuffer(); | |||
| MemoryAudioSource source { buffer, true, false }; | |||
| source.setLooping (false); | |||
| source.prepareToPlay (blockSize, 44100.0); | |||
| play (source, channelInfo); | |||
| auto copy = buffer; | |||
| copy.setSize (buffer.getNumChannels(), blockSize, true, true, false); | |||
| expect (bufferToFill == copy); | |||
| play (source, channelInfo); | |||
| expect (isSilent (bufferToFill)); | |||
| } | |||
| beginTest ("A short buffer with looping is played multiple times"); | |||
| { | |||
| auto buffer = getShortBuffer(); | |||
| MemoryAudioSource source { buffer, true, false }; | |||
| source.setLooping (true); | |||
| source.prepareToPlay (blockSize, 44100.0); | |||
| play (source, channelInfo); | |||
| for (int sample = 0; sample < buffer.getNumSamples(); ++sample) | |||
| expect (bufferToFill.getSample (0, sample + buffer.getNumSamples()) == buffer.getSample (0, sample)); | |||
| expect (! isSilent (bufferToFill)); | |||
| } | |||
| beginTest ("A long buffer without looping is played once"); | |||
| { | |||
| auto buffer = getLongBuffer(); | |||
| MemoryAudioSource source { buffer, true, false }; | |||
| source.setLooping (false); | |||
| source.prepareToPlay (blockSize, 44100.0); | |||
| play (source, channelInfo); | |||
| auto copy = buffer; | |||
| copy.setSize (buffer.getNumChannels(), blockSize, true, true, false); | |||
| expect (bufferToFill == copy); | |||
| for (int i = 0; i < 10; ++i) | |||
| play (source, channelInfo); | |||
| expect (isSilent (bufferToFill)); | |||
| } | |||
| beginTest ("A long buffer with looping is played multiple times"); | |||
| { | |||
| auto buffer = getLongBuffer(); | |||
| MemoryAudioSource source { buffer, true, false }; | |||
| source.setLooping (true); | |||
| source.prepareToPlay (blockSize, 44100.0); | |||
| for (int i = 0; i < 100; ++i) | |||
| { | |||
| play (source, channelInfo); | |||
| expect (bufferToFill.getSample (0, 0) == buffer.getSample (0, (i * blockSize) % buffer.getNumSamples())); | |||
| } | |||
| } | |||
| } | |||
| static AudioBuffer<float> getTestBuffer (int length) | |||
| { | |||
| AudioBuffer<float> buffer { 2, length }; | |||
| for (int channel = 0; channel < buffer.getNumChannels(); ++channel) | |||
| for (int sample = 0; sample < buffer.getNumSamples(); ++sample) | |||
| buffer.setSample (channel, sample, jmap ((float) sample, 0.0f, (float) length, -1.0f, 1.0f)); | |||
| return buffer; | |||
| } | |||
| static AudioBuffer<float> getShortBuffer() { return getTestBuffer (5); } | |||
| static AudioBuffer<float> getLongBuffer() { return getTestBuffer (1000); } | |||
| static void play (MemoryAudioSource& source, AudioSourceChannelInfo& info) | |||
| { | |||
| info.clearActiveBufferRegion(); | |||
| source.getNextAudioBlock (info); | |||
| } | |||
| static bool isSilent (const AudioBuffer<float>& b) | |||
| { | |||
| for (int channel = 0; channel < b.getNumChannels(); ++channel) | |||
| if (b.findMinMax (channel, 0, b.getNumSamples()) != Range<float>{}) | |||
| return false; | |||
| return true; | |||
| } | |||
| }; | |||
| static MemoryAudioSourceTests memoryAudioSourceTests; | |||
| #endif | |||
| } // namespace juce | |||
| @@ -675,6 +675,19 @@ public: | |||
| return noErr; | |||
| } | |||
| #if defined (MAC_OS_X_VERSION_10_12) | |||
| case kAudioUnitProperty_AUHostIdentifier: | |||
| { | |||
| if (inDataSize < sizeof (AUHostVersionIdentifier)) | |||
| return kAudioUnitErr_InvalidPropertyValue; | |||
| const auto* identifier = static_cast<const AUHostVersionIdentifier*> (inData); | |||
| PluginHostType::hostIdReportedByWrapper = String::fromCFString (identifier->hostName); | |||
| return noErr; | |||
| } | |||
| #endif | |||
| default: break; | |||
| } | |||
| } | |||
| @@ -612,6 +612,10 @@ public: | |||
| { | |||
| centreWithSize (getWidth(), getHeight()); | |||
| } | |||
| if (auto* processor = getAudioProcessor()) | |||
| if (auto* editor = processor->getActiveEditor()) | |||
| setResizable (editor->isResizable(), false); | |||
| #endif | |||
| } | |||
| @@ -927,11 +927,13 @@ public: | |||
| { | |||
| if (auto* pluginInstance = getPluginInstance()) | |||
| { | |||
| if (pluginInstance->hasEditor() && name != nullptr | |||
| && strcmp (name, Vst::ViewType::kEditor) == 0) | |||
| { | |||
| const auto mayCreateEditor = pluginInstance->hasEditor() | |||
| && name != nullptr | |||
| && std::strcmp (name, Vst::ViewType::kEditor) == 0 | |||
| && pluginInstance->getActiveEditor() == nullptr; | |||
| if (mayCreateEditor) | |||
| return new JuceVST3Editor (*this, *pluginInstance); | |||
| } | |||
| } | |||
| return nullptr; | |||
| @@ -126,6 +126,5 @@ | |||
| #define JUCE_STANDALONE_FILTER_WINDOW_USE_KIOSK_MODE (JUCE_IOS || JUCE_ANDROID) | |||
| #endif | |||
| #include "utility/juce_PluginHostType.h" | |||
| #include "utility/juce_CreatePluginFilter.h" | |||
| #include "VST/juce_VSTCallbackHandler.h" | |||
| @@ -1,439 +0,0 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library. | |||
| Copyright (c) 2020 - 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 6 End-User License | |||
| Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020). | |||
| End User License Agreement: www.juce.com/juce-6-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. | |||
| ============================================================================== | |||
| */ | |||
| namespace juce | |||
| { | |||
| //============================================================================== | |||
| /** | |||
| A useful utility class to determine the host or DAW in which your plugin is | |||
| loaded. | |||
| Declare a PluginHostType object in your class to use it. | |||
| @tags{Audio} | |||
| */ | |||
| class PluginHostType | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| PluginHostType() : type (getHostType()) {} | |||
| PluginHostType (const PluginHostType& other) = default; | |||
| PluginHostType& operator= (const PluginHostType& other) = default; | |||
| //============================================================================== | |||
| /** Represents the host type and also its version for some hosts. */ | |||
| enum HostType | |||
| { | |||
| UnknownHost, /**< Represents an unknown host. */ | |||
| AbletonLive6, /**< Represents Ableton Live 6. */ | |||
| AbletonLive7, /**< Represents Ableton Live 7. */ | |||
| AbletonLive8, /**< Represents Ableton Live 8. */ | |||
| AbletonLive9, /**< Represents Ableton Live 9. */ | |||
| AbletonLive10, /**< Represents Ableton Live 10. */ | |||
| AbletonLiveGeneric, /**< Represents Ableton Live. */ | |||
| AdobeAudition, /**< Represents Adobe Audition. */ | |||
| AdobePremierePro, /**< Represents Adobe Premiere Pro. */ | |||
| AppleGarageBand, /**< Represents Apple GarageBand. */ | |||
| AppleLogic, /**< Represents Apple Logic Pro. */ | |||
| AppleMainStage, /**< Represents Apple Main Stage. */ | |||
| Ardour, /**< Represents Ardour. */ | |||
| AvidProTools, /**< Represents Avid Pro Tools. */ | |||
| BitwigStudio, /**< Represents Bitwig Studio. */ | |||
| CakewalkSonar8, /**< Represents Cakewalk Sonar 8. */ | |||
| CakewalkSonarGeneric, /**< Represents Cakewalk Sonar. */ | |||
| CakewalkByBandlab, /**< Represents Cakewalk by Bandlab. */ | |||
| DaVinciResolve, /**< Represents DaVinci Resolve. */ | |||
| DigitalPerformer, /**< Represents Digital Performer. */ | |||
| FinalCut, /**< Represents Apple Final Cut Pro. */ | |||
| FruityLoops, /**< Represents Fruity Loops. */ | |||
| JUCEPluginHost, /**< Represents the JUCE AudioPluginHost */ | |||
| MagixSamplitude, /**< Represents Magix Samplitude. */ | |||
| MagixSequoia, /**< Represents Magix Sequoia. */ | |||
| MergingPyramix, /**< Represents Merging Pyramix. */ | |||
| MuseReceptorGeneric, /**< Represents Muse Receptor. */ | |||
| pluginval, /**< Represents pluginval. */ | |||
| Reaper, /**< Represents Cockos Reaper. */ | |||
| Reason, /**< Represents Reason. */ | |||
| Renoise, /**< Represents Renoise. */ | |||
| SADiE, /**< Represents SADiE. */ | |||
| SteinbergCubase4, /**< Represents Steinberg Cubase 4. */ | |||
| SteinbergCubase5, /**< Represents Steinberg Cubase 5. */ | |||
| SteinbergCubase5Bridged, /**< Represents Steinberg Cubase 5 Bridged. */ | |||
| SteinbergCubase6, /**< Represents Steinberg Cubase 6. */ | |||
| SteinbergCubase7, /**< Represents Steinberg Cubase 7. */ | |||
| SteinbergCubase8, /**< Represents Steinberg Cubase 8. */ | |||
| SteinbergCubase8_5, /**< Represents Steinberg Cubase 8.5. */ | |||
| SteinbergCubase9, /**< Represents Steinberg Cubase 9. */ | |||
| SteinbergCubase9_5, /**< Represents Steinberg Cubase 9.5. */ | |||
| SteinbergCubase10, /**< Represents Steinberg Cubase 10. */ | |||
| SteinbergCubase10_5, /**< Represents Steinberg Cubase 10.5. */ | |||
| SteinbergCubaseGeneric, /**< Represents Steinberg Cubase. */ | |||
| SteinbergNuendo3, /**< Represents Steinberg Nuendo 3. */ | |||
| SteinbergNuendo4, /**< Represents Steinberg Nuendo 4. */ | |||
| SteinbergNuendo5, /**< Represents Steinberg Nuendo 5. */ | |||
| SteinbergNuendoGeneric, /**< Represents Steinberg Nuendo. */ | |||
| SteinbergWavelab5, /**< Represents Steinberg Wavelab 5. */ | |||
| SteinbergWavelab6, /**< Represents Steinberg Wavelab 6. */ | |||
| SteinbergWavelab7, /**< Represents Steinberg Wavelab 7. */ | |||
| SteinbergWavelab8, /**< Represents Steinberg Wavelab 8. */ | |||
| SteinbergWavelabGeneric, /**< Represents Steinberg Wavelab. */ | |||
| SteinbergTestHost, /**< Represents Steinberg's VST3 Test Host. */ | |||
| StudioOne, /**< Represents PreSonus Studio One. */ | |||
| Tracktion3, /**< Represents Tracktion 3. */ | |||
| TracktionGeneric, /**< Represents Tracktion. */ | |||
| TracktionWaveform, /**< Represents Tracktion Waveform. */ | |||
| VBVSTScanner, /**< Represents VB Audio VST Scanner. */ | |||
| ViennaEnsemblePro, /**< Represents Vienna Ensemble Pro. */ | |||
| WaveBurner /**< Represents Apple WaveBurner. */ | |||
| }; | |||
| HostType type; | |||
| //============================================================================== | |||
| /** Returns true if the host is any version of Ableton Live. */ | |||
| bool isAbletonLive() const noexcept { return type == AbletonLive6 || type == AbletonLive7 || type == AbletonLive8 | |||
| || type == AbletonLive9 || type == AbletonLive10 || type == AbletonLiveGeneric; } | |||
| /** Returns true if the host is Adobe Audition. */ | |||
| bool isAdobeAudition() const noexcept { return type == AdobeAudition; } | |||
| /** Returns true if the host is Ardour. */ | |||
| bool isArdour() const noexcept { return type == Ardour; } | |||
| /** Returns true if the host is Bitwig Studio. */ | |||
| bool isBitwigStudio() const noexcept { return type == BitwigStudio; } | |||
| /** Returns true if the host is any version of Steinberg Cubase. */ | |||
| bool isCubase() const noexcept { return type == SteinbergCubase4 || type == SteinbergCubase5 || type == SteinbergCubase5Bridged || type == SteinbergCubase6 | |||
| || type == SteinbergCubase7 || type == SteinbergCubase8 || type == SteinbergCubase8_5 || type == SteinbergCubase9 | |||
| || type == SteinbergCubase9_5 || type == SteinbergCubase10 || type == SteinbergCubase10_5 || type == SteinbergCubaseGeneric; } | |||
| /** Returns true if the host is Steinberg Cubase 7 or later. */ | |||
| bool isCubase7orLater() const noexcept { return isCubase() && ! (type == SteinbergCubase4 || type == SteinbergCubase5 || type == SteinbergCubase6); } | |||
| /** Returns true if the host is Steinberg Cubase 5 Bridged. */ | |||
| bool isCubaseBridged() const noexcept { return type == SteinbergCubase5Bridged; } | |||
| /** Returns true if the host is DaVinci Resolve. */ | |||
| bool isDaVinciResolve() const noexcept { return type == DaVinciResolve; } | |||
| /** Returns true if the host is Digital Performer. */ | |||
| bool isDigitalPerformer() const noexcept { return type == DigitalPerformer; } | |||
| /** Returns true if the host is Apple Final Cut Pro. */ | |||
| bool isFinalCut() const noexcept { return type == FinalCut; } | |||
| /** Returns true if the host is Fruity Loops. */ | |||
| bool isFruityLoops() const noexcept { return type == FruityLoops; } | |||
| /** Returns true if the host is Apple GarageBand. */ | |||
| bool isGarageBand() const noexcept { return type == AppleGarageBand; } | |||
| /** Returns true if the host is the JUCE AudioPluginHost */ | |||
| bool isJUCEPluginHost() const noexcept { return type == JUCEPluginHost; } | |||
| /** Returns true if the host is Apple Logic Pro. */ | |||
| bool isLogic() const noexcept { return type == AppleLogic; } | |||
| /** Returns true if the host is Apple MainStage. */ | |||
| bool isMainStage() const noexcept { return type == AppleMainStage; } | |||
| /** Returns true if the host is any version of Steinberg Nuendo. */ | |||
| bool isNuendo() const noexcept { return type == SteinbergNuendo3 || type == SteinbergNuendo4 || type == SteinbergNuendo5 || type == SteinbergNuendoGeneric; } | |||
| /** Returns true if the host is pluginval. */ | |||
| bool isPluginval() const noexcept { return type == pluginval; } | |||
| /** Returns true if the host is Adobe Premiere Pro. */ | |||
| bool isPremiere() const noexcept { return type == AdobePremierePro; } | |||
| /** Returns true if the host is Avid Pro Tools. */ | |||
| bool isProTools() const noexcept { return type == AvidProTools; } | |||
| /** Returns true if the host is Merging Pyramix. */ | |||
| bool isPyramix() const noexcept { return type == MergingPyramix; } | |||
| /** Returns true if the host is Muse Receptor. */ | |||
| bool isReceptor() const noexcept { return type == MuseReceptorGeneric; } | |||
| /** Returns true if the host is Cockos Reaper. */ | |||
| bool isReaper() const noexcept { return type == Reaper; } | |||
| /** Returns true if the host is Reason. */ | |||
| bool isReason() const noexcept { return type == Reason; } | |||
| /** Returns true if the host is Renoise. */ | |||
| bool isRenoise() const noexcept { return type == Renoise; } | |||
| /** Returns true if the host is SADiE. */ | |||
| bool isSADiE() const noexcept { return type == SADiE; } | |||
| /** Returns true if the host is Magix Samplitude. */ | |||
| bool isSamplitude() const noexcept { return type == MagixSamplitude; } | |||
| /** Returns true if the host is Magix Sequoia. */ | |||
| bool isSequoia() const noexcept { return type == MagixSequoia; } | |||
| /** Returns true if the host is any version of Cakewalk Sonar. */ | |||
| bool isSonar() const noexcept { return type == CakewalkSonar8 || type == CakewalkSonarGeneric || type == CakewalkByBandlab; } | |||
| /** Returns true if the host is Steinberg's VST3 Test Host. */ | |||
| bool isSteinbergTestHost() const noexcept { return type == SteinbergTestHost; } | |||
| /** Returns true if the host is any product from Steinberg. */ | |||
| bool isSteinberg() const noexcept { return isCubase() || isNuendo() || isWavelab() || isSteinbergTestHost(); } | |||
| /** Returns true if the host is PreSonus Studio One. */ | |||
| bool isStudioOne() const noexcept { return type == StudioOne; } | |||
| /** Returns true if the host is any version of Tracktion. */ | |||
| bool isTracktion() const noexcept { return type == Tracktion3 || type == TracktionGeneric || isTracktionWaveform(); } | |||
| /** Returns true if the host is Tracktion Waveform. */ | |||
| bool isTracktionWaveform() const noexcept { return type == TracktionWaveform; } | |||
| /** Returns true if the host is VB Audio VST Scanner. */ | |||
| bool isVBVSTScanner() const noexcept { return type == VBVSTScanner; } | |||
| /** Returns true if the host is Vienna Ensemble Pro. */ | |||
| bool isViennaEnsemblePro() const noexcept { return type == ViennaEnsemblePro; } | |||
| /** Returns true if the host is Apple WaveBurner. */ | |||
| bool isWaveBurner() const noexcept { return type == WaveBurner; } | |||
| /** Returns true if the host is any version of Steinberg WaveLab. */ | |||
| bool isWavelab() const noexcept { return isWavelabLegacy() || type == SteinbergWavelab7 || type == SteinbergWavelab8 || type == SteinbergWavelabGeneric; } | |||
| /** Returns true if the host is Steinberg WaveLab 6 or below. */ | |||
| bool isWavelabLegacy() const noexcept { return type == SteinbergWavelab5 || type == SteinbergWavelab6; } | |||
| //============================================================================== | |||
| /** Returns a human-readable description of the host. */ | |||
| const char* getHostDescription() const noexcept | |||
| { | |||
| switch (type) | |||
| { | |||
| case AbletonLive6: return "Ableton Live 6"; | |||
| case AbletonLive7: return "Ableton Live 7"; | |||
| case AbletonLive8: return "Ableton Live 8"; | |||
| case AbletonLive9: return "Ableton Live 9"; | |||
| case AbletonLive10: return "Ableton Live 10"; | |||
| case AbletonLiveGeneric: return "Ableton Live"; | |||
| case AdobeAudition: return "Adobe Audition"; | |||
| case AdobePremierePro: return "Adobe Premiere"; | |||
| case AppleGarageBand: return "Apple GarageBand"; | |||
| case AppleLogic: return "Apple Logic"; | |||
| case AppleMainStage: return "Apple MainStage"; | |||
| case Ardour: return "Ardour"; | |||
| case AvidProTools: return "ProTools"; | |||
| case BitwigStudio: return "Bitwig Studio"; | |||
| case CakewalkSonar8: return "Cakewalk Sonar 8"; | |||
| case CakewalkSonarGeneric: return "Cakewalk Sonar"; | |||
| case CakewalkByBandlab: return "Cakewalk by Bandlab"; | |||
| case DaVinciResolve: return "DaVinci Resolve"; | |||
| case DigitalPerformer: return "DigitalPerformer"; | |||
| case FinalCut: return "Final Cut"; | |||
| case FruityLoops: return "FruityLoops"; | |||
| case JUCEPluginHost: return "JUCE AudioPluginHost"; | |||
| case MagixSamplitude: return "Magix Samplitude"; | |||
| case MagixSequoia: return "Magix Sequoia"; | |||
| case pluginval: return "pluginval"; | |||
| case MergingPyramix: return "Pyramix"; | |||
| case MuseReceptorGeneric: return "Muse Receptor"; | |||
| case Reaper: return "Reaper"; | |||
| case Reason: return "Reason"; | |||
| case Renoise: return "Renoise"; | |||
| case SADiE: return "SADiE"; | |||
| case SteinbergCubase4: return "Steinberg Cubase 4"; | |||
| case SteinbergCubase5: return "Steinberg Cubase 5"; | |||
| case SteinbergCubase5Bridged: return "Steinberg Cubase 5 Bridged"; | |||
| case SteinbergCubase6: return "Steinberg Cubase 6"; | |||
| case SteinbergCubase7: return "Steinberg Cubase 7"; | |||
| case SteinbergCubase8: return "Steinberg Cubase 8"; | |||
| case SteinbergCubase8_5: return "Steinberg Cubase 8.5"; | |||
| case SteinbergCubase9: return "Steinberg Cubase 9"; | |||
| case SteinbergCubase9_5: return "Steinberg Cubase 9.5"; | |||
| case SteinbergCubase10: return "Steinberg Cubase 10"; | |||
| case SteinbergCubase10_5: return "Steinberg Cubase 10.5"; | |||
| case SteinbergCubaseGeneric: return "Steinberg Cubase"; | |||
| case SteinbergNuendo3: return "Steinberg Nuendo 3"; | |||
| case SteinbergNuendo4: return "Steinberg Nuendo 4"; | |||
| case SteinbergNuendo5: return "Steinberg Nuendo 5"; | |||
| case SteinbergNuendoGeneric: return "Steinberg Nuendo"; | |||
| case SteinbergWavelab5: return "Steinberg Wavelab 5"; | |||
| case SteinbergWavelab6: return "Steinberg Wavelab 6"; | |||
| case SteinbergWavelab7: return "Steinberg Wavelab 7"; | |||
| case SteinbergWavelab8: return "Steinberg Wavelab 8"; | |||
| case SteinbergWavelabGeneric: return "Steinberg Wavelab"; | |||
| case SteinbergTestHost: return "Steinberg TestHost"; | |||
| case StudioOne: return "Studio One"; | |||
| case Tracktion3: return "Tracktion 3"; | |||
| case TracktionGeneric: return "Tracktion"; | |||
| case TracktionWaveform: return "Tracktion Waveform"; | |||
| case VBVSTScanner: return "VBVSTScanner"; | |||
| case ViennaEnsemblePro: return "Vienna Ensemble Pro"; | |||
| case WaveBurner: return "WaveBurner"; | |||
| case UnknownHost: | |||
| default: break; | |||
| } | |||
| return "Unknown"; | |||
| } | |||
| //============================================================================== | |||
| /** Returns true if the plugin is connected with Inter-App Audio on iOS. */ | |||
| bool isInterAppAudioConnected() const; | |||
| /** Switches to the host application when Inter-App Audio is used on iOS. */ | |||
| void switchToHostApplication() const; | |||
| /** Gets the host app's icon when Inter-App Audio is used on iOS. */ | |||
| Image getHostIcon (int size) const; | |||
| //============================================================================== | |||
| /** Returns the complete absolute path of the host application executable. */ | |||
| static String getHostPath() | |||
| { | |||
| return File::getSpecialLocation (File::hostApplicationPath).getFullPathName(); | |||
| } | |||
| //============================================================================== | |||
| /** | |||
| Returns the plug-in format via which the plug-in file was loaded. This value is | |||
| identical to AudioProcessor::wrapperType of the main audio processor of this | |||
| plug-in. This function is useful for code that does not have access to the | |||
| plug-in's main audio processor. | |||
| @see AudioProcessor::wrapperType | |||
| */ | |||
| static AudioProcessor::WrapperType getPluginLoadedAs() noexcept { return jucePlugInClientCurrentWrapperType; } | |||
| /** Returns true if the AudioProcessor instance is an AAX plug-in running in AudioSuite. */ | |||
| static bool isInAAXAudioSuite (AudioProcessor&); | |||
| //============================================================================== | |||
| #ifndef DOXYGEN | |||
| // @internal | |||
| static AudioProcessor::WrapperType jucePlugInClientCurrentWrapperType; | |||
| static std::function<bool (AudioProcessor&)> jucePlugInIsRunningInAudioSuiteFn; | |||
| #endif | |||
| private: | |||
| static HostType getHostType() | |||
| { | |||
| auto hostPath = getHostPath(); | |||
| auto hostFilename = File (hostPath).getFileName(); | |||
| #if JUCE_MAC | |||
| if (hostPath.containsIgnoreCase ("Final Cut Pro.app")) return FinalCut; | |||
| if (hostPath.containsIgnoreCase ("Final Cut Pro Trial.app")) return FinalCut; | |||
| if (hostPath.containsIgnoreCase ("Live 6")) return AbletonLive6; | |||
| if (hostPath.containsIgnoreCase ("Live 7")) return AbletonLive7; | |||
| if (hostPath.containsIgnoreCase ("Live 8")) return AbletonLive8; | |||
| if (hostPath.containsIgnoreCase ("Live 9")) return AbletonLive9; | |||
| if (hostPath.containsIgnoreCase ("Live 10")) return AbletonLive10; | |||
| if (hostFilename.containsIgnoreCase ("Live")) return AbletonLiveGeneric; | |||
| if (hostFilename.containsIgnoreCase ("Adobe Premiere")) return AdobePremierePro; | |||
| if (hostFilename.containsIgnoreCase ("GarageBand")) return AppleGarageBand; | |||
| if (hostFilename.containsIgnoreCase ("Logic")) return AppleLogic; | |||
| if (hostFilename.containsIgnoreCase ("MainStage")) return AppleMainStage; | |||
| if (hostFilename.containsIgnoreCase ("Pro Tools")) return AvidProTools; | |||
| if (hostFilename.containsIgnoreCase ("Nuendo 3")) return SteinbergNuendo3; | |||
| if (hostFilename.containsIgnoreCase ("Nuendo 4")) return SteinbergNuendo4; | |||
| if (hostFilename.containsIgnoreCase ("Nuendo 5")) return SteinbergNuendo5; | |||
| if (hostFilename.containsIgnoreCase ("Nuendo")) return SteinbergNuendoGeneric; | |||
| if (hostFilename.containsIgnoreCase ("Cubase 4")) return SteinbergCubase4; | |||
| if (hostFilename.containsIgnoreCase ("Cubase 5")) return SteinbergCubase5; | |||
| if (hostFilename.containsIgnoreCase ("Cubase 6")) return SteinbergCubase6; | |||
| if (hostFilename.containsIgnoreCase ("Cubase 7")) return SteinbergCubase7; | |||
| if (hostPath.containsIgnoreCase ("Cubase 8.app")) return SteinbergCubase8; | |||
| if (hostPath.containsIgnoreCase ("Cubase 8.5.app")) return SteinbergCubase8_5; | |||
| if (hostPath.containsIgnoreCase ("Cubase 9.app")) return SteinbergCubase9; | |||
| if (hostPath.containsIgnoreCase ("Cubase 9.5.app")) return SteinbergCubase9_5; | |||
| if (hostPath.containsIgnoreCase ("Cubase 10.app")) return SteinbergCubase10; | |||
| if (hostPath.containsIgnoreCase ("Cubase 10.5.app")) return SteinbergCubase10_5; | |||
| if (hostFilename.containsIgnoreCase ("Cubase")) return SteinbergCubaseGeneric; | |||
| if (hostPath.containsIgnoreCase ("Wavelab 7")) return SteinbergWavelab7; | |||
| if (hostPath.containsIgnoreCase ("Wavelab 8")) return SteinbergWavelab8; | |||
| if (hostFilename.containsIgnoreCase ("Wavelab")) return SteinbergWavelabGeneric; | |||
| if (hostFilename.containsIgnoreCase ("WaveBurner")) return WaveBurner; | |||
| if (hostPath.containsIgnoreCase ("Digital Performer")) return DigitalPerformer; | |||
| if (hostFilename.containsIgnoreCase ("reaper")) return Reaper; | |||
| if (hostFilename.containsIgnoreCase ("Reason")) return Reason; | |||
| if (hostPath.containsIgnoreCase ("Studio One")) return StudioOne; | |||
| if (hostFilename.startsWithIgnoreCase ("Waveform")) return TracktionWaveform; | |||
| if (hostPath.containsIgnoreCase ("Tracktion 3")) return Tracktion3; | |||
| if (hostFilename.containsIgnoreCase ("Tracktion")) return TracktionGeneric; | |||
| if (hostFilename.containsIgnoreCase ("Renoise")) return Renoise; | |||
| if (hostFilename.containsIgnoreCase ("Resolve")) return DaVinciResolve; | |||
| if (hostFilename.startsWith ("Bitwig")) return BitwigStudio; | |||
| if (hostFilename.containsIgnoreCase ("OsxFL")) return FruityLoops; | |||
| if (hostFilename.containsIgnoreCase ("pluginval")) return pluginval; | |||
| if (hostFilename.containsIgnoreCase ("AudioPluginHost")) return JUCEPluginHost; | |||
| if (hostFilename.containsIgnoreCase ("Vienna Ensemble Pro")) return ViennaEnsemblePro; | |||
| #elif JUCE_WINDOWS | |||
| if (hostFilename.containsIgnoreCase ("Live 6")) return AbletonLive6; | |||
| if (hostFilename.containsIgnoreCase ("Live 7")) return AbletonLive7; | |||
| if (hostFilename.containsIgnoreCase ("Live 8")) return AbletonLive8; | |||
| if (hostFilename.containsIgnoreCase ("Live 9")) return AbletonLive9; | |||
| if (hostFilename.containsIgnoreCase ("Live 10")) return AbletonLive10; | |||
| if (hostFilename.containsIgnoreCase ("Live ")) return AbletonLiveGeneric; | |||
| if (hostFilename.containsIgnoreCase ("Audition")) return AdobeAudition; | |||
| if (hostFilename.containsIgnoreCase ("Adobe Premiere")) return AdobePremierePro; | |||
| if (hostFilename.containsIgnoreCase ("ProTools")) return AvidProTools; | |||
| if (hostPath.containsIgnoreCase ("SONAR 8")) return CakewalkSonar8; | |||
| if (hostFilename.containsIgnoreCase ("SONAR")) return CakewalkSonarGeneric; | |||
| if (hostFilename.containsIgnoreCase ("Cakewalk.exe")) return CakewalkByBandlab; | |||
| if (hostFilename.containsIgnoreCase ("GarageBand")) return AppleGarageBand; | |||
| if (hostFilename.containsIgnoreCase ("Logic")) return AppleLogic; | |||
| if (hostFilename.containsIgnoreCase ("MainStage")) return AppleMainStage; | |||
| if (hostFilename.startsWithIgnoreCase ("Waveform")) return TracktionWaveform; | |||
| if (hostPath.containsIgnoreCase ("Tracktion 3")) return Tracktion3; | |||
| if (hostFilename.containsIgnoreCase ("Tracktion")) return TracktionGeneric; | |||
| if (hostFilename.containsIgnoreCase ("reaper")) return Reaper; | |||
| if (hostFilename.containsIgnoreCase ("Cubase4")) return SteinbergCubase4; | |||
| if (hostFilename.containsIgnoreCase ("Cubase5")) return SteinbergCubase5; | |||
| if (hostFilename.containsIgnoreCase ("Cubase6")) return SteinbergCubase6; | |||
| if (hostFilename.containsIgnoreCase ("Cubase7")) return SteinbergCubase7; | |||
| if (hostFilename.containsIgnoreCase ("Cubase8.exe")) return SteinbergCubase8; | |||
| if (hostFilename.containsIgnoreCase ("Cubase8.5.exe")) return SteinbergCubase8_5; | |||
| // Later version of Cubase scan plug-ins with a separate executable "vst2xscanner" | |||
| if (hostFilename.containsIgnoreCase ("Cubase9.5.exe") | |||
| || hostPath.containsIgnoreCase ("Cubase 9.5")) return SteinbergCubase9_5; | |||
| if (hostFilename.containsIgnoreCase ("Cubase9.exe") | |||
| || hostPath.containsIgnoreCase ("Cubase 9")) return SteinbergCubase9; | |||
| if (hostFilename.containsIgnoreCase ("Cubase10.5.exe") | |||
| || hostPath.containsIgnoreCase ("Cubase 10.5")) return SteinbergCubase10_5; | |||
| if (hostFilename.containsIgnoreCase ("Cubase10.exe") | |||
| || hostPath.containsIgnoreCase ("Cubase 10")) return SteinbergCubase10; | |||
| if (hostFilename.containsIgnoreCase ("Cubase")) return SteinbergCubaseGeneric; | |||
| if (hostFilename.containsIgnoreCase ("VSTBridgeApp")) return SteinbergCubase5Bridged; | |||
| if (hostPath.containsIgnoreCase ("Wavelab 5")) return SteinbergWavelab5; | |||
| if (hostPath.containsIgnoreCase ("Wavelab 6")) return SteinbergWavelab6; | |||
| if (hostPath.containsIgnoreCase ("Wavelab 7")) return SteinbergWavelab7; | |||
| if (hostPath.containsIgnoreCase ("Wavelab 8")) return SteinbergWavelab8; | |||
| if (hostPath.containsIgnoreCase ("Nuendo")) return SteinbergNuendoGeneric; | |||
| if (hostFilename.containsIgnoreCase ("Wavelab")) return SteinbergWavelabGeneric; | |||
| if (hostFilename.containsIgnoreCase ("TestHost")) return SteinbergTestHost; | |||
| if (hostFilename.containsIgnoreCase ("rm-host")) return MuseReceptorGeneric; | |||
| if (hostFilename.startsWith ("FL")) return FruityLoops; | |||
| if (hostFilename.contains ("ilbridge.")) return FruityLoops; | |||
| if (hostPath.containsIgnoreCase ("Studio One")) return StudioOne; | |||
| if (hostPath.containsIgnoreCase ("Digital Performer")) return DigitalPerformer; | |||
| if (hostFilename.containsIgnoreCase ("VST_Scanner")) return VBVSTScanner; | |||
| if (hostPath.containsIgnoreCase ("Merging Technologies")) return MergingPyramix; | |||
| if (hostFilename.startsWithIgnoreCase ("Sam")) return MagixSamplitude; | |||
| if (hostFilename.startsWithIgnoreCase ("Sequoia")) return MagixSequoia; | |||
| if (hostFilename.containsIgnoreCase ("Reason")) return Reason; | |||
| if (hostFilename.containsIgnoreCase ("Renoise")) return Renoise; | |||
| if (hostFilename.containsIgnoreCase ("Resolve")) return DaVinciResolve; | |||
| if (hostPath.containsIgnoreCase ("Bitwig Studio")) return BitwigStudio; | |||
| if (hostFilename.containsIgnoreCase ("Sadie")) return SADiE; | |||
| if (hostFilename.containsIgnoreCase ("pluginval")) return pluginval; | |||
| if (hostFilename.containsIgnoreCase ("AudioPluginHost")) return JUCEPluginHost; | |||
| if (hostFilename.containsIgnoreCase ("Vienna Ensemble Pro")) return ViennaEnsemblePro; | |||
| #elif JUCE_LINUX | |||
| if (hostFilename.containsIgnoreCase ("Ardour")) return Ardour; | |||
| if (hostFilename.startsWithIgnoreCase ("Waveform")) return TracktionWaveform; | |||
| if (hostFilename.containsIgnoreCase ("Tracktion")) return TracktionGeneric; | |||
| if (hostFilename.startsWith ("Bitwig")) return BitwigStudio; | |||
| if (hostFilename.containsIgnoreCase ("pluginval")) return pluginval; | |||
| if (hostFilename.containsIgnoreCase ("AudioPluginHost")) return JUCEPluginHost; | |||
| #elif JUCE_IOS | |||
| #elif JUCE_ANDROID | |||
| #else | |||
| #error | |||
| #endif | |||
| return UnknownHost; | |||
| } | |||
| }; | |||
| } // namespace juce | |||
| @@ -34,9 +34,6 @@ | |||
| namespace juce | |||
| { | |||
| AudioProcessor::WrapperType PluginHostType::jucePlugInClientCurrentWrapperType = AudioProcessor::wrapperType_Undefined; | |||
| std::function<bool (AudioProcessor&)> PluginHostType::jucePlugInIsRunningInAudioSuiteFn = nullptr; | |||
| #if JucePlugin_Build_Unity | |||
| bool juce_isRunningInUnity() { return PluginHostType::getPluginLoadedAs() == AudioProcessor::wrapperType_Unity; } | |||
| #endif | |||
| @@ -146,67 +143,3 @@ std::function<bool (AudioProcessor&)> PluginHostType::jucePlugInIsRunningInAudio | |||
| #endif | |||
| } // namespace juce | |||
| using namespace juce; | |||
| //============================================================================== | |||
| #if JucePlugin_Enable_IAA && JucePlugin_Build_Standalone && JUCE_IOS && (! JUCE_USE_CUSTOM_PLUGIN_STANDALONE_APP) | |||
| extern bool JUCE_CALLTYPE juce_isInterAppAudioConnected(); | |||
| extern void JUCE_CALLTYPE juce_switchToHostApplication(); | |||
| extern Image JUCE_CALLTYPE juce_getIAAHostIcon (int); | |||
| #endif | |||
| bool PluginHostType::isInterAppAudioConnected() const | |||
| { | |||
| #if JucePlugin_Enable_IAA && JucePlugin_Build_Standalone && JUCE_IOS && (! JUCE_USE_CUSTOM_PLUGIN_STANDALONE_APP) | |||
| if (getPluginLoadedAs() == AudioProcessor::wrapperType_Standalone) | |||
| return juce_isInterAppAudioConnected(); | |||
| #endif | |||
| return false; | |||
| } | |||
| void PluginHostType::switchToHostApplication() const | |||
| { | |||
| #if JucePlugin_Enable_IAA && JucePlugin_Build_Standalone && JUCE_IOS && (! JUCE_USE_CUSTOM_PLUGIN_STANDALONE_APP) | |||
| if (getPluginLoadedAs() == AudioProcessor::wrapperType_Standalone) | |||
| juce_switchToHostApplication(); | |||
| #endif | |||
| } | |||
| bool PluginHostType::isInAAXAudioSuite (AudioProcessor& processor) | |||
| { | |||
| #if JucePlugin_Build_AAX | |||
| if (PluginHostType::getPluginLoadedAs() == AudioProcessor::wrapperType_AAX | |||
| && jucePlugInIsRunningInAudioSuiteFn != nullptr) | |||
| { | |||
| return jucePlugInIsRunningInAudioSuiteFn (processor); | |||
| } | |||
| #endif | |||
| ignoreUnused (processor); | |||
| return false; | |||
| } | |||
| namespace juce { | |||
| extern Image JUCE_API getIconFromApplication (const String&, const int); | |||
| Image PluginHostType::getHostIcon (int size) const | |||
| { | |||
| ignoreUnused (size); | |||
| #if JucePlugin_Enable_IAA && JucePlugin_Build_Standalone && JUCE_IOS && (! JUCE_USE_CUSTOM_PLUGIN_STANDALONE_APP) | |||
| if (isInterAppAudioConnected()) | |||
| return juce_getIAAHostIcon (size); | |||
| #endif | |||
| #if JUCE_MAC | |||
| String bundlePath (getHostPath().upToLastOccurrenceOf (".app", true, true)); | |||
| return getIconFromApplication (bundlePath, size); | |||
| #endif | |||
| return Image(); | |||
| } | |||
| } | |||
| @@ -499,17 +499,11 @@ public: | |||
| float normaliseParamValue (float scaledValue) const noexcept | |||
| { | |||
| if (discrete) | |||
| return scaledValue / (getNumSteps() - 1); | |||
| return (scaledValue - minValue) / range; | |||
| } | |||
| float scaleParamValue (float normalisedValue) const noexcept | |||
| { | |||
| if (discrete) | |||
| return normalisedValue * (getNumSteps() - 1); | |||
| return minValue + (range * normalisedValue); | |||
| } | |||
| @@ -1223,23 +1217,33 @@ public: | |||
| } | |||
| //============================================================================== | |||
| int getNumPrograms() override | |||
| struct ScopedFactoryPresets | |||
| { | |||
| CFArrayRef presets; | |||
| UInt32 sz = sizeof (CFArrayRef); | |||
| int num = 0; | |||
| ScopedFactoryPresets (AudioUnit& au) | |||
| { | |||
| UInt32 sz = sizeof (CFArrayRef); | |||
| if (AudioUnitGetProperty (audioUnit, kAudioUnitProperty_FactoryPresets, | |||
| kAudioUnitScope_Global, 0, &presets, &sz) == noErr) | |||
| AudioUnitGetProperty (au, kAudioUnitProperty_FactoryPresets, | |||
| kAudioUnitScope_Global, 0, &presets, &sz); | |||
| } | |||
| ~ScopedFactoryPresets() | |||
| { | |||
| if (presets != nullptr) | |||
| { | |||
| num = (int) CFArrayGetCount (presets); | |||
| CFRelease (presets); | |||
| } | |||
| } | |||
| return num; | |||
| CFArrayRef presets = nullptr; | |||
| }; | |||
| int getNumPrograms() override | |||
| { | |||
| ScopedFactoryPresets factoryPresets { audioUnit }; | |||
| if (factoryPresets.presets != nullptr) | |||
| return (int) CFArrayGetCount (factoryPresets.presets); | |||
| return 0; | |||
| } | |||
| int getCurrentProgram() override | |||
| @@ -1256,33 +1260,26 @@ public: | |||
| void setCurrentProgram (int newIndex) override | |||
| { | |||
| AUPreset current; | |||
| current.presetNumber = newIndex; | |||
| ScopedFactoryPresets factoryPresets { audioUnit }; | |||
| CFArrayRef presets; | |||
| UInt32 sz = sizeof (CFArrayRef); | |||
| if (AudioUnitGetProperty (audioUnit, kAudioUnitProperty_FactoryPresets, | |||
| kAudioUnitScope_Global, 0, &presets, &sz) == noErr) | |||
| if (factoryPresets.presets != nullptr | |||
| && newIndex < (int) CFArrayGetCount (factoryPresets.presets)) | |||
| { | |||
| if (auto* p = (const AUPreset*) CFArrayGetValueAtIndex (presets, newIndex)) | |||
| current.presetName = p->presetName; | |||
| AUPreset current; | |||
| current.presetNumber = newIndex; | |||
| CFRelease (presets); | |||
| } | |||
| if (auto* p = static_cast<const AUPreset*> (CFArrayGetValueAtIndex (factoryPresets.presets, newIndex))) | |||
| current.presetName = p->presetName; | |||
| AudioUnitSetProperty (audioUnit, kAudioUnitProperty_PresentPreset, | |||
| kAudioUnitScope_Global, 0, ¤t, sizeof (AUPreset)); | |||
| AudioUnitSetProperty (audioUnit, kAudioUnitProperty_PresentPreset, | |||
| kAudioUnitScope_Global, 0, ¤t, sizeof (AUPreset)); | |||
| sendAllParametersChangedEvents(); | |||
| sendAllParametersChangedEvents(); | |||
| } | |||
| } | |||
| const String getProgramName (int index) override | |||
| { | |||
| String s; | |||
| CFArrayRef presets; | |||
| UInt32 sz = sizeof (CFArrayRef); | |||
| if (index == -1) | |||
| { | |||
| AUPreset current; | |||
| @@ -1294,27 +1291,20 @@ public: | |||
| AudioUnitGetProperty (audioUnit, kAudioUnitProperty_PresentPreset, | |||
| kAudioUnitScope_Global, 0, ¤t, &prstsz); | |||
| s = String::fromCFString (current.presetName); | |||
| return String::fromCFString (current.presetName); | |||
| } | |||
| else if (AudioUnitGetProperty (audioUnit, kAudioUnitProperty_FactoryPresets, | |||
| kAudioUnitScope_Global, 0, &presets, &sz) == noErr) | |||
| ScopedFactoryPresets factoryPresets { audioUnit }; | |||
| if (factoryPresets.presets != nullptr) | |||
| { | |||
| for (CFIndex i = 0; i < CFArrayGetCount (presets); ++i) | |||
| { | |||
| if (auto* p = (const AUPreset*) CFArrayGetValueAtIndex (presets, i)) | |||
| { | |||
| for (CFIndex i = 0; i < CFArrayGetCount (factoryPresets.presets); ++i) | |||
| if (auto* p = static_cast<const AUPreset*> (CFArrayGetValueAtIndex (factoryPresets.presets, i))) | |||
| if (p->presetNumber == index) | |||
| { | |||
| s = String::fromCFString (p->presetName); | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| CFRelease (presets); | |||
| return String::fromCFString (p->presetName); | |||
| } | |||
| return s; | |||
| return {}; | |||
| } | |||
| void changeProgramName (int /*index*/, const String& /*newName*/) override | |||
| @@ -1471,7 +1461,7 @@ public: | |||
| info.defaultValue, | |||
| (info.flags & kAudioUnitParameterFlag_NonRealTime) == 0, | |||
| isDiscrete, | |||
| isDiscrete ? (int) (info.maxValue + 1.0f) : AudioProcessor::getDefaultNumParameterSteps(), | |||
| isDiscrete ? (int) (info.maxValue - info.minValue + 1.0f) : AudioProcessor::getDefaultNumParameterSteps(), | |||
| isBoolean, | |||
| label, | |||
| (info.flags & kAudioUnitParameterFlag_ValuesHaveStrings) != 0); | |||
| @@ -266,31 +266,33 @@ static Steinberg::Vst::SpeakerArrangement getVst3SpeakerArrangement (const Audio | |||
| { | |||
| using namespace Steinberg::Vst::SpeakerArr; | |||
| if (channels == AudioChannelSet::disabled()) return kEmpty; | |||
| else if (channels == AudioChannelSet::mono()) return kMono; | |||
| else if (channels == AudioChannelSet::stereo()) return kStereo; | |||
| else if (channels == AudioChannelSet::createLCR()) return k30Cine; | |||
| else if (channels == AudioChannelSet::createLRS()) return k30Music; | |||
| else if (channels == AudioChannelSet::createLCRS()) return k40Cine; | |||
| else if (channels == AudioChannelSet::create5point0()) return k50; | |||
| else if (channels == AudioChannelSet::create5point1()) return k51; | |||
| else if (channels == AudioChannelSet::create6point0()) return k60Cine; | |||
| else if (channels == AudioChannelSet::create6point1()) return k61Cine; | |||
| else if (channels == AudioChannelSet::create6point0Music()) return k60Music; | |||
| else if (channels == AudioChannelSet::create6point1Music()) return k61Music; | |||
| else if (channels == AudioChannelSet::create7point0()) return k70Music; | |||
| else if (channels == AudioChannelSet::create7point0SDDS()) return k70Cine; | |||
| else if (channels == AudioChannelSet::create7point1()) return k71CineSideFill; | |||
| else if (channels == AudioChannelSet::create7point1SDDS()) return k71Cine; | |||
| else if (channels == AudioChannelSet::ambisonic()) return kAmbi1stOrderACN; | |||
| else if (channels == AudioChannelSet::quadraphonic()) return k40Music; | |||
| else if (channels == AudioChannelSet::create7point0point2()) return k71_2 & ~(Steinberg::Vst::kSpeakerLfe); | |||
| else if (channels == AudioChannelSet::create7point1point2()) return k71_2; | |||
| else if (channels == AudioChannelSet::ambisonic (0)) return (1ull << 20); | |||
| else if (channels == AudioChannelSet::ambisonic (1)) return (1ull << 20) | (1ull << 21) | (1ull << 22) | (1ull << 23); | |||
| if (channels == AudioChannelSet::disabled()) return kEmpty; | |||
| if (channels == AudioChannelSet::mono()) return kMono; | |||
| if (channels == AudioChannelSet::stereo()) return kStereo; | |||
| if (channels == AudioChannelSet::createLCR()) return k30Cine; | |||
| if (channels == AudioChannelSet::createLRS()) return k30Music; | |||
| if (channels == AudioChannelSet::createLCRS()) return k40Cine; | |||
| if (channels == AudioChannelSet::create5point0()) return k50; | |||
| if (channels == AudioChannelSet::create5point1()) return k51; | |||
| if (channels == AudioChannelSet::create6point0()) return k60Cine; | |||
| if (channels == AudioChannelSet::create6point1()) return k61Cine; | |||
| if (channels == AudioChannelSet::create6point0Music()) return k60Music; | |||
| if (channels == AudioChannelSet::create6point1Music()) return k61Music; | |||
| if (channels == AudioChannelSet::create7point0()) return k70Music; | |||
| if (channels == AudioChannelSet::create7point0SDDS()) return k70Cine; | |||
| if (channels == AudioChannelSet::create7point1()) return k71CineSideFill; | |||
| if (channels == AudioChannelSet::create7point1SDDS()) return k71Cine; | |||
| if (channels == AudioChannelSet::ambisonic()) return kAmbi1stOrderACN; | |||
| if (channels == AudioChannelSet::quadraphonic()) return k40Music; | |||
| if (channels == AudioChannelSet::create7point0point2()) return k71_2 & ~(Steinberg::Vst::kSpeakerLfe); | |||
| if (channels == AudioChannelSet::create7point1point2()) return k71_2; | |||
| if (channels == AudioChannelSet::create7point0point4()) return k71_4 & ~(Steinberg::Vst::kSpeakerLfe); | |||
| if (channels == AudioChannelSet::create7point1point4()) return k71_4; | |||
| if (channels == AudioChannelSet::ambisonic (0)) return (1ull << 20); | |||
| if (channels == AudioChannelSet::ambisonic (1)) return (1ull << 20) | (1ull << 21) | (1ull << 22) | (1ull << 23); | |||
| #if VST_VERSION >= 0x030608 | |||
| else if (channels == AudioChannelSet::ambisonic (2)) return kAmbi2cdOrderACN; | |||
| else if (channels == AudioChannelSet::ambisonic (3)) return kAmbi3rdOrderACN; | |||
| if (channels == AudioChannelSet::ambisonic (2)) return kAmbi2cdOrderACN; | |||
| if (channels == AudioChannelSet::ambisonic (3)) return kAmbi3rdOrderACN; | |||
| #endif | |||
| Steinberg::Vst::SpeakerArrangement result = 0; | |||
| @@ -307,32 +309,36 @@ static AudioChannelSet getChannelSetForSpeakerArrangement (Steinberg::Vst::Speak | |||
| { | |||
| using namespace Steinberg::Vst::SpeakerArr; | |||
| if (arr == kEmpty) return AudioChannelSet::disabled(); | |||
| else if (arr == kMono) return AudioChannelSet::mono(); | |||
| else if (arr == kStereo) return AudioChannelSet::stereo(); | |||
| else if (arr == k30Cine) return AudioChannelSet::createLCR(); | |||
| else if (arr == k30Music) return AudioChannelSet::createLRS(); | |||
| else if (arr == k40Cine) return AudioChannelSet::createLCRS(); | |||
| else if (arr == k50) return AudioChannelSet::create5point0(); | |||
| else if (arr == k51) return AudioChannelSet::create5point1(); | |||
| else if (arr == k60Cine) return AudioChannelSet::create6point0(); | |||
| else if (arr == k61Cine) return AudioChannelSet::create6point1(); | |||
| else if (arr == k60Music) return AudioChannelSet::create6point0Music(); | |||
| else if (arr == k61Music) return AudioChannelSet::create6point1Music(); | |||
| else if (arr == k70Music) return AudioChannelSet::create7point0(); | |||
| else if (arr == k70Cine) return AudioChannelSet::create7point0SDDS(); | |||
| else if (arr == k71CineSideFill) return AudioChannelSet::create7point1(); | |||
| else if (arr == k71Cine) return AudioChannelSet::create7point1SDDS(); | |||
| else if (arr == kAmbi1stOrderACN) return AudioChannelSet::ambisonic(); | |||
| else if (arr == k40Music) return AudioChannelSet::quadraphonic(); | |||
| else if (arr == k71_2) return AudioChannelSet::create7point1point2(); | |||
| else if (arr == (k71_2 & ~(Steinberg::Vst::kSpeakerLfe))) return AudioChannelSet::create7point0point2(); | |||
| else if (arr == (1 << 20)) return AudioChannelSet::ambisonic (0); | |||
| else if (arr == ((1 << 20) | (1 << 21) | (1 << 22) | (1 << 23))) return AudioChannelSet::ambisonic (1); | |||
| #if VST_VERSION >= 0x030608 | |||
| else if (arr == kAmbi2cdOrderACN) return AudioChannelSet::ambisonic (2); | |||
| else if (arr == kAmbi3rdOrderACN) return AudioChannelSet::ambisonic (3); | |||
| #endif | |||
| switch (arr) | |||
| { | |||
| case kEmpty: return AudioChannelSet::disabled(); | |||
| case kMono: return AudioChannelSet::mono(); | |||
| case kStereo: return AudioChannelSet::stereo(); | |||
| case k30Cine: return AudioChannelSet::createLCR(); | |||
| case k30Music: return AudioChannelSet::createLRS(); | |||
| case k40Cine: return AudioChannelSet::createLCRS(); | |||
| case k50: return AudioChannelSet::create5point0(); | |||
| case k51: return AudioChannelSet::create5point1(); | |||
| case k60Cine: return AudioChannelSet::create6point0(); | |||
| case k61Cine: return AudioChannelSet::create6point1(); | |||
| case k60Music: return AudioChannelSet::create6point0Music(); | |||
| case k61Music: return AudioChannelSet::create6point1Music(); | |||
| case k70Music: return AudioChannelSet::create7point0(); | |||
| case k70Cine: return AudioChannelSet::create7point0SDDS(); | |||
| case k71CineSideFill: return AudioChannelSet::create7point1(); | |||
| case k71Cine: return AudioChannelSet::create7point1SDDS(); | |||
| case k40Music: return AudioChannelSet::quadraphonic(); | |||
| case k71_2: return AudioChannelSet::create7point1point2(); | |||
| case k71_2 & ~(Steinberg::Vst::kSpeakerLfe): return AudioChannelSet::create7point0point2(); | |||
| case k71_4: return AudioChannelSet::create7point1point4(); | |||
| case k71_4 & ~(Steinberg::Vst::kSpeakerLfe): return AudioChannelSet::create7point0point4(); | |||
| case (1 << 20): return AudioChannelSet::ambisonic (0); | |||
| case kAmbi1stOrderACN: return AudioChannelSet::ambisonic (1); | |||
| #if VST_VERSION >= 0x030608 | |||
| case kAmbi2cdOrderACN: return AudioChannelSet::ambisonic (2); | |||
| case kAmbi3rdOrderACN: return AudioChannelSet::ambisonic (3); | |||
| #endif | |||
| } | |||
| AudioChannelSet result; | |||
| @@ -253,3 +253,4 @@ struct AutoResizingNSViewComponentWithParent : public AutoResizingNSViewCompone | |||
| #include "utilities/juce_AudioParameterChoice.cpp" | |||
| #include "utilities/juce_ParameterAttachments.cpp" | |||
| #include "utilities/juce_AudioProcessorValueTreeState.cpp" | |||
| #include "utilities/juce_PluginHostType.cpp" | |||
| @@ -142,3 +142,4 @@ | |||
| #include "utilities/juce_AudioParameterChoice.h" | |||
| #include "utilities/juce_ParameterAttachments.h" | |||
| #include "utilities/juce_AudioProcessorValueTreeState.h" | |||
| #include "utilities/juce_PluginHostType.h" | |||
| @@ -0,0 +1,309 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library. | |||
| Copyright (c) 2020 - 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 6 End-User License | |||
| Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020). | |||
| End User License Agreement: www.juce.com/juce-6-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. | |||
| ============================================================================== | |||
| */ | |||
| #if JucePlugin_Enable_IAA && JucePlugin_Build_Standalone && JUCE_IOS && (! JUCE_USE_CUSTOM_PLUGIN_STANDALONE_APP) | |||
| bool JUCE_CALLTYPE juce_isInterAppAudioConnected(); | |||
| void JUCE_CALLTYPE juce_switchToHostApplication(); | |||
| juce::Image JUCE_CALLTYPE juce_getIAAHostIcon (int); | |||
| #endif | |||
| namespace juce | |||
| { | |||
| Image JUCE_API getIconFromApplication (const String&, const int); | |||
| AudioProcessor::WrapperType PluginHostType::jucePlugInClientCurrentWrapperType = AudioProcessor::wrapperType_Undefined; | |||
| std::function<bool (AudioProcessor&)> PluginHostType::jucePlugInIsRunningInAudioSuiteFn = nullptr; | |||
| String PluginHostType::hostIdReportedByWrapper; | |||
| bool PluginHostType::isInterAppAudioConnected() const | |||
| { | |||
| #if JucePlugin_Enable_IAA && JucePlugin_Build_Standalone && JUCE_IOS && (! JUCE_USE_CUSTOM_PLUGIN_STANDALONE_APP) | |||
| if (getPluginLoadedAs() == AudioProcessor::wrapperType_Standalone) | |||
| return juce_isInterAppAudioConnected(); | |||
| #endif | |||
| return false; | |||
| } | |||
| void PluginHostType::switchToHostApplication() const | |||
| { | |||
| #if JucePlugin_Enable_IAA && JucePlugin_Build_Standalone && JUCE_IOS && (! JUCE_USE_CUSTOM_PLUGIN_STANDALONE_APP) | |||
| if (getPluginLoadedAs() == AudioProcessor::wrapperType_Standalone) | |||
| juce_switchToHostApplication(); | |||
| #endif | |||
| } | |||
| bool PluginHostType::isInAAXAudioSuite (AudioProcessor& processor) | |||
| { | |||
| #if JucePlugin_Build_AAX | |||
| if (PluginHostType::getPluginLoadedAs() == AudioProcessor::wrapperType_AAX | |||
| && jucePlugInIsRunningInAudioSuiteFn != nullptr) | |||
| { | |||
| return jucePlugInIsRunningInAudioSuiteFn (processor); | |||
| } | |||
| #endif | |||
| ignoreUnused (processor); | |||
| return false; | |||
| } | |||
| Image PluginHostType::getHostIcon (int size) const | |||
| { | |||
| ignoreUnused (size); | |||
| #if JucePlugin_Enable_IAA && JucePlugin_Build_Standalone && JUCE_IOS && (! JUCE_USE_CUSTOM_PLUGIN_STANDALONE_APP) | |||
| if (isInterAppAudioConnected()) | |||
| return juce_getIAAHostIcon (size); | |||
| #endif | |||
| #if JUCE_MAC | |||
| String bundlePath (getHostPath().upToLastOccurrenceOf (".app", true, true)); | |||
| return getIconFromApplication (bundlePath, size); | |||
| #endif | |||
| return Image(); | |||
| } | |||
| const char* PluginHostType::getHostDescription() const noexcept | |||
| { | |||
| switch (type) | |||
| { | |||
| case AbletonLive6: return "Ableton Live 6"; | |||
| case AbletonLive7: return "Ableton Live 7"; | |||
| case AbletonLive8: return "Ableton Live 8"; | |||
| case AbletonLive9: return "Ableton Live 9"; | |||
| case AbletonLive10: return "Ableton Live 10"; | |||
| case AbletonLiveGeneric: return "Ableton Live"; | |||
| case AdobeAudition: return "Adobe Audition"; | |||
| case AdobePremierePro: return "Adobe Premiere"; | |||
| case AppleGarageBand: return "Apple GarageBand"; | |||
| case AppleLogic: return "Apple Logic"; | |||
| case AppleMainStage: return "Apple MainStage"; | |||
| case Ardour: return "Ardour"; | |||
| case AvidProTools: return "ProTools"; | |||
| case BitwigStudio: return "Bitwig Studio"; | |||
| case CakewalkSonar8: return "Cakewalk Sonar 8"; | |||
| case CakewalkSonarGeneric: return "Cakewalk Sonar"; | |||
| case CakewalkByBandlab: return "Cakewalk by Bandlab"; | |||
| case DaVinciResolve: return "DaVinci Resolve"; | |||
| case DigitalPerformer: return "DigitalPerformer"; | |||
| case FinalCut: return "Final Cut"; | |||
| case FruityLoops: return "FruityLoops"; | |||
| case JUCEPluginHost: return "JUCE AudioPluginHost"; | |||
| case MagixSamplitude: return "Magix Samplitude"; | |||
| case MagixSequoia: return "Magix Sequoia"; | |||
| case pluginval: return "pluginval"; | |||
| case MergingPyramix: return "Pyramix"; | |||
| case MuseReceptorGeneric: return "Muse Receptor"; | |||
| case Reaper: return "Reaper"; | |||
| case Reason: return "Reason"; | |||
| case Renoise: return "Renoise"; | |||
| case SADiE: return "SADiE"; | |||
| case SteinbergCubase4: return "Steinberg Cubase 4"; | |||
| case SteinbergCubase5: return "Steinberg Cubase 5"; | |||
| case SteinbergCubase5Bridged: return "Steinberg Cubase 5 Bridged"; | |||
| case SteinbergCubase6: return "Steinberg Cubase 6"; | |||
| case SteinbergCubase7: return "Steinberg Cubase 7"; | |||
| case SteinbergCubase8: return "Steinberg Cubase 8"; | |||
| case SteinbergCubase8_5: return "Steinberg Cubase 8.5"; | |||
| case SteinbergCubase9: return "Steinberg Cubase 9"; | |||
| case SteinbergCubase9_5: return "Steinberg Cubase 9.5"; | |||
| case SteinbergCubase10: return "Steinberg Cubase 10"; | |||
| case SteinbergCubase10_5: return "Steinberg Cubase 10.5"; | |||
| case SteinbergCubaseGeneric: return "Steinberg Cubase"; | |||
| case SteinbergNuendo3: return "Steinberg Nuendo 3"; | |||
| case SteinbergNuendo4: return "Steinberg Nuendo 4"; | |||
| case SteinbergNuendo5: return "Steinberg Nuendo 5"; | |||
| case SteinbergNuendoGeneric: return "Steinberg Nuendo"; | |||
| case SteinbergWavelab5: return "Steinberg Wavelab 5"; | |||
| case SteinbergWavelab6: return "Steinberg Wavelab 6"; | |||
| case SteinbergWavelab7: return "Steinberg Wavelab 7"; | |||
| case SteinbergWavelab8: return "Steinberg Wavelab 8"; | |||
| case SteinbergWavelabGeneric: return "Steinberg Wavelab"; | |||
| case SteinbergTestHost: return "Steinberg TestHost"; | |||
| case StudioOne: return "Studio One"; | |||
| case Tracktion3: return "Tracktion 3"; | |||
| case TracktionGeneric: return "Tracktion"; | |||
| case TracktionWaveform: return "Tracktion Waveform"; | |||
| case VBVSTScanner: return "VBVSTScanner"; | |||
| case ViennaEnsemblePro: return "Vienna Ensemble Pro"; | |||
| case WaveBurner: return "WaveBurner"; | |||
| case UnknownHost: | |||
| default: break; | |||
| } | |||
| return "Unknown"; | |||
| } | |||
| PluginHostType::HostType PluginHostType::getHostType() | |||
| { | |||
| auto hostPath = getHostPath(); | |||
| auto hostFilename = File (hostPath).getFileName(); | |||
| #if JUCE_MAC | |||
| if (hostPath.containsIgnoreCase ("Final Cut Pro.app")) return FinalCut; | |||
| if (hostPath.containsIgnoreCase ("Final Cut Pro Trial.app")) return FinalCut; | |||
| if (hostPath.containsIgnoreCase ("Live 6")) return AbletonLive6; | |||
| if (hostPath.containsIgnoreCase ("Live 7")) return AbletonLive7; | |||
| if (hostPath.containsIgnoreCase ("Live 8")) return AbletonLive8; | |||
| if (hostPath.containsIgnoreCase ("Live 9")) return AbletonLive9; | |||
| if (hostPath.containsIgnoreCase ("Live 10")) return AbletonLive10; | |||
| if (hostFilename.containsIgnoreCase ("Live")) return AbletonLiveGeneric; | |||
| if (hostFilename.containsIgnoreCase ("Adobe Premiere")) return AdobePremierePro; | |||
| if (hostFilename.containsIgnoreCase ("GarageBand")) return AppleGarageBand; | |||
| if (hostFilename.containsIgnoreCase ("Logic")) return AppleLogic; | |||
| if (hostFilename.containsIgnoreCase ("MainStage")) return AppleMainStage; | |||
| if (hostFilename.containsIgnoreCase ("Pro Tools")) return AvidProTools; | |||
| if (hostFilename.containsIgnoreCase ("Nuendo 3")) return SteinbergNuendo3; | |||
| if (hostFilename.containsIgnoreCase ("Nuendo 4")) return SteinbergNuendo4; | |||
| if (hostFilename.containsIgnoreCase ("Nuendo 5")) return SteinbergNuendo5; | |||
| if (hostFilename.containsIgnoreCase ("Nuendo")) return SteinbergNuendoGeneric; | |||
| if (hostFilename.containsIgnoreCase ("Cubase 4")) return SteinbergCubase4; | |||
| if (hostFilename.containsIgnoreCase ("Cubase 5")) return SteinbergCubase5; | |||
| if (hostFilename.containsIgnoreCase ("Cubase 6")) return SteinbergCubase6; | |||
| if (hostFilename.containsIgnoreCase ("Cubase 7")) return SteinbergCubase7; | |||
| if (hostPath.containsIgnoreCase ("Cubase 8.app")) return SteinbergCubase8; | |||
| if (hostPath.containsIgnoreCase ("Cubase 8.5.app")) return SteinbergCubase8_5; | |||
| if (hostPath.containsIgnoreCase ("Cubase 9.app")) return SteinbergCubase9; | |||
| if (hostPath.containsIgnoreCase ("Cubase 9.5.app")) return SteinbergCubase9_5; | |||
| if (hostPath.containsIgnoreCase ("Cubase 10.app")) return SteinbergCubase10; | |||
| if (hostPath.containsIgnoreCase ("Cubase 10.5.app")) return SteinbergCubase10_5; | |||
| if (hostFilename.containsIgnoreCase ("Cubase")) return SteinbergCubaseGeneric; | |||
| if (hostPath.containsIgnoreCase ("Wavelab 7")) return SteinbergWavelab7; | |||
| if (hostPath.containsIgnoreCase ("Wavelab 8")) return SteinbergWavelab8; | |||
| if (hostFilename.containsIgnoreCase ("Wavelab")) return SteinbergWavelabGeneric; | |||
| if (hostFilename.containsIgnoreCase ("WaveBurner")) return WaveBurner; | |||
| if (hostPath.containsIgnoreCase ("Digital Performer")) return DigitalPerformer; | |||
| if (hostFilename.containsIgnoreCase ("reaper")) return Reaper; | |||
| if (hostFilename.containsIgnoreCase ("Reason")) return Reason; | |||
| if (hostPath.containsIgnoreCase ("Studio One")) return StudioOne; | |||
| if (hostFilename.startsWithIgnoreCase ("Waveform")) return TracktionWaveform; | |||
| if (hostPath.containsIgnoreCase ("Tracktion 3")) return Tracktion3; | |||
| if (hostFilename.containsIgnoreCase ("Tracktion")) return TracktionGeneric; | |||
| if (hostFilename.containsIgnoreCase ("Renoise")) return Renoise; | |||
| if (hostFilename.containsIgnoreCase ("Resolve")) return DaVinciResolve; | |||
| if (hostFilename.startsWith ("Bitwig")) return BitwigStudio; | |||
| if (hostFilename.containsIgnoreCase ("OsxFL")) return FruityLoops; | |||
| if (hostFilename.containsIgnoreCase ("pluginval")) return pluginval; | |||
| if (hostFilename.containsIgnoreCase ("AudioPluginHost")) return JUCEPluginHost; | |||
| if (hostFilename.containsIgnoreCase ("Vienna Ensemble Pro")) return ViennaEnsemblePro; | |||
| if (hostIdReportedByWrapper == "com.apple.logic.pro") return AppleLogic; | |||
| if (hostIdReportedByWrapper == "com.apple.garageband") return AppleGarageBand; | |||
| if (hostIdReportedByWrapper == "com.apple.mainstage") return AppleMainStage; | |||
| const auto procName = nsStringToJuce ([[NSRunningApplication currentApplication] localizedName]); | |||
| const auto matchesInOrder = [&] (const StringArray& strings) | |||
| { | |||
| return procName.matchesWildcard ("AUHostingService*(" + strings.joinIntoString ("*") + ")", false); | |||
| }; | |||
| // Depending on localization settings, spaces are not always plain ascii spaces | |||
| if (matchesInOrder ({ "Logic", "Pro" })) return AppleLogic; | |||
| if (matchesInOrder ({ "GarageBand" })) return AppleGarageBand; | |||
| if (matchesInOrder ({ "MainStage" })) return AppleMainStage; | |||
| if (matchesInOrder ({ "Final", "Cut", "Pro" })) return FinalCut; | |||
| #elif JUCE_WINDOWS | |||
| if (hostFilename.containsIgnoreCase ("Live 6")) return AbletonLive6; | |||
| if (hostFilename.containsIgnoreCase ("Live 7")) return AbletonLive7; | |||
| if (hostFilename.containsIgnoreCase ("Live 8")) return AbletonLive8; | |||
| if (hostFilename.containsIgnoreCase ("Live 9")) return AbletonLive9; | |||
| if (hostFilename.containsIgnoreCase ("Live 10")) return AbletonLive10; | |||
| if (hostFilename.containsIgnoreCase ("Live ")) return AbletonLiveGeneric; | |||
| if (hostFilename.containsIgnoreCase ("Audition")) return AdobeAudition; | |||
| if (hostFilename.containsIgnoreCase ("Adobe Premiere")) return AdobePremierePro; | |||
| if (hostFilename.containsIgnoreCase ("ProTools")) return AvidProTools; | |||
| if (hostPath.containsIgnoreCase ("SONAR 8")) return CakewalkSonar8; | |||
| if (hostFilename.containsIgnoreCase ("SONAR")) return CakewalkSonarGeneric; | |||
| if (hostFilename.containsIgnoreCase ("Cakewalk.exe")) return CakewalkByBandlab; | |||
| if (hostFilename.containsIgnoreCase ("GarageBand")) return AppleGarageBand; | |||
| if (hostFilename.containsIgnoreCase ("Logic")) return AppleLogic; | |||
| if (hostFilename.containsIgnoreCase ("MainStage")) return AppleMainStage; | |||
| if (hostFilename.startsWithIgnoreCase ("Waveform")) return TracktionWaveform; | |||
| if (hostPath.containsIgnoreCase ("Tracktion 3")) return Tracktion3; | |||
| if (hostFilename.containsIgnoreCase ("Tracktion")) return TracktionGeneric; | |||
| if (hostFilename.containsIgnoreCase ("reaper")) return Reaper; | |||
| if (hostFilename.containsIgnoreCase ("Cubase4")) return SteinbergCubase4; | |||
| if (hostFilename.containsIgnoreCase ("Cubase5")) return SteinbergCubase5; | |||
| if (hostFilename.containsIgnoreCase ("Cubase6")) return SteinbergCubase6; | |||
| if (hostFilename.containsIgnoreCase ("Cubase7")) return SteinbergCubase7; | |||
| if (hostFilename.containsIgnoreCase ("Cubase8.exe")) return SteinbergCubase8; | |||
| if (hostFilename.containsIgnoreCase ("Cubase8.5.exe")) return SteinbergCubase8_5; | |||
| // Later version of Cubase scan plug-ins with a separate executable "vst2xscanner" | |||
| if (hostFilename.containsIgnoreCase ("Cubase9.5.exe") | |||
| || hostPath.containsIgnoreCase ("Cubase 9.5")) return SteinbergCubase9_5; | |||
| if (hostFilename.containsIgnoreCase ("Cubase9.exe") | |||
| || hostPath.containsIgnoreCase ("Cubase 9")) return SteinbergCubase9; | |||
| if (hostFilename.containsIgnoreCase ("Cubase10.5.exe") | |||
| || hostPath.containsIgnoreCase ("Cubase 10.5")) return SteinbergCubase10_5; | |||
| if (hostFilename.containsIgnoreCase ("Cubase10.exe") | |||
| || hostPath.containsIgnoreCase ("Cubase 10")) return SteinbergCubase10; | |||
| if (hostFilename.containsIgnoreCase ("Cubase")) return SteinbergCubaseGeneric; | |||
| if (hostFilename.containsIgnoreCase ("VSTBridgeApp")) return SteinbergCubase5Bridged; | |||
| if (hostPath.containsIgnoreCase ("Wavelab 5")) return SteinbergWavelab5; | |||
| if (hostPath.containsIgnoreCase ("Wavelab 6")) return SteinbergWavelab6; | |||
| if (hostPath.containsIgnoreCase ("Wavelab 7")) return SteinbergWavelab7; | |||
| if (hostPath.containsIgnoreCase ("Wavelab 8")) return SteinbergWavelab8; | |||
| if (hostPath.containsIgnoreCase ("Nuendo")) return SteinbergNuendoGeneric; | |||
| if (hostFilename.containsIgnoreCase ("Wavelab")) return SteinbergWavelabGeneric; | |||
| if (hostFilename.containsIgnoreCase ("TestHost")) return SteinbergTestHost; | |||
| if (hostFilename.containsIgnoreCase ("rm-host")) return MuseReceptorGeneric; | |||
| if (hostFilename.startsWith ("FL")) return FruityLoops; | |||
| if (hostFilename.contains ("ilbridge.")) return FruityLoops; | |||
| if (hostPath.containsIgnoreCase ("Studio One")) return StudioOne; | |||
| if (hostPath.containsIgnoreCase ("Digital Performer")) return DigitalPerformer; | |||
| if (hostFilename.containsIgnoreCase ("VST_Scanner")) return VBVSTScanner; | |||
| if (hostPath.containsIgnoreCase ("Merging Technologies")) return MergingPyramix; | |||
| if (hostFilename.startsWithIgnoreCase ("Sam")) return MagixSamplitude; | |||
| if (hostFilename.startsWithIgnoreCase ("Sequoia")) return MagixSequoia; | |||
| if (hostFilename.containsIgnoreCase ("Reason")) return Reason; | |||
| if (hostFilename.containsIgnoreCase ("Renoise")) return Renoise; | |||
| if (hostFilename.containsIgnoreCase ("Resolve")) return DaVinciResolve; | |||
| if (hostPath.containsIgnoreCase ("Bitwig Studio")) return BitwigStudio; | |||
| if (hostFilename.containsIgnoreCase ("Sadie")) return SADiE; | |||
| if (hostFilename.containsIgnoreCase ("pluginval")) return pluginval; | |||
| if (hostFilename.containsIgnoreCase ("AudioPluginHost")) return JUCEPluginHost; | |||
| if (hostFilename.containsIgnoreCase ("Vienna Ensemble Pro")) return ViennaEnsemblePro; | |||
| #elif JUCE_LINUX | |||
| if (hostFilename.containsIgnoreCase ("Ardour")) return Ardour; | |||
| if (hostFilename.startsWithIgnoreCase ("Waveform")) return TracktionWaveform; | |||
| if (hostFilename.containsIgnoreCase ("Tracktion")) return TracktionGeneric; | |||
| if (hostFilename.startsWith ("Bitwig")) return BitwigStudio; | |||
| if (hostFilename.containsIgnoreCase ("pluginval")) return pluginval; | |||
| if (hostFilename.containsIgnoreCase ("AudioPluginHost")) return JUCEPluginHost; | |||
| #elif JUCE_IOS | |||
| #elif JUCE_ANDROID | |||
| #else | |||
| #error | |||
| #endif | |||
| return UnknownHost; | |||
| } | |||
| } // namespace juce | |||
| @@ -0,0 +1,242 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library. | |||
| Copyright (c) 2020 - 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 6 End-User License | |||
| Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020). | |||
| End User License Agreement: www.juce.com/juce-6-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. | |||
| ============================================================================== | |||
| */ | |||
| namespace juce | |||
| { | |||
| //============================================================================== | |||
| /** | |||
| A useful utility class to determine the host or DAW in which your plugin is | |||
| loaded. | |||
| Declare a PluginHostType object in your class to use it. | |||
| @tags{Audio} | |||
| */ | |||
| class PluginHostType | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| PluginHostType() : type (getHostType()) {} | |||
| PluginHostType (const PluginHostType& other) = default; | |||
| PluginHostType& operator= (const PluginHostType& other) = default; | |||
| //============================================================================== | |||
| /** Represents the host type and also its version for some hosts. */ | |||
| enum HostType | |||
| { | |||
| UnknownHost, /**< Represents an unknown host. */ | |||
| AbletonLive6, /**< Represents Ableton Live 6. */ | |||
| AbletonLive7, /**< Represents Ableton Live 7. */ | |||
| AbletonLive8, /**< Represents Ableton Live 8. */ | |||
| AbletonLive9, /**< Represents Ableton Live 9. */ | |||
| AbletonLive10, /**< Represents Ableton Live 10. */ | |||
| AbletonLiveGeneric, /**< Represents Ableton Live. */ | |||
| AdobeAudition, /**< Represents Adobe Audition. */ | |||
| AdobePremierePro, /**< Represents Adobe Premiere Pro. */ | |||
| AppleGarageBand, /**< Represents Apple GarageBand. */ | |||
| AppleLogic, /**< Represents Apple Logic Pro. */ | |||
| AppleMainStage, /**< Represents Apple Main Stage. */ | |||
| Ardour, /**< Represents Ardour. */ | |||
| AvidProTools, /**< Represents Avid Pro Tools. */ | |||
| BitwigStudio, /**< Represents Bitwig Studio. */ | |||
| CakewalkSonar8, /**< Represents Cakewalk Sonar 8. */ | |||
| CakewalkSonarGeneric, /**< Represents Cakewalk Sonar. */ | |||
| CakewalkByBandlab, /**< Represents Cakewalk by Bandlab. */ | |||
| DaVinciResolve, /**< Represents DaVinci Resolve. */ | |||
| DigitalPerformer, /**< Represents Digital Performer. */ | |||
| FinalCut, /**< Represents Apple Final Cut Pro. */ | |||
| FruityLoops, /**< Represents Fruity Loops. */ | |||
| JUCEPluginHost, /**< Represents the JUCE AudioPluginHost */ | |||
| MagixSamplitude, /**< Represents Magix Samplitude. */ | |||
| MagixSequoia, /**< Represents Magix Sequoia. */ | |||
| MergingPyramix, /**< Represents Merging Pyramix. */ | |||
| MuseReceptorGeneric, /**< Represents Muse Receptor. */ | |||
| pluginval, /**< Represents pluginval. */ | |||
| Reaper, /**< Represents Cockos Reaper. */ | |||
| Reason, /**< Represents Reason. */ | |||
| Renoise, /**< Represents Renoise. */ | |||
| SADiE, /**< Represents SADiE. */ | |||
| SteinbergCubase4, /**< Represents Steinberg Cubase 4. */ | |||
| SteinbergCubase5, /**< Represents Steinberg Cubase 5. */ | |||
| SteinbergCubase5Bridged, /**< Represents Steinberg Cubase 5 Bridged. */ | |||
| SteinbergCubase6, /**< Represents Steinberg Cubase 6. */ | |||
| SteinbergCubase7, /**< Represents Steinberg Cubase 7. */ | |||
| SteinbergCubase8, /**< Represents Steinberg Cubase 8. */ | |||
| SteinbergCubase8_5, /**< Represents Steinberg Cubase 8.5. */ | |||
| SteinbergCubase9, /**< Represents Steinberg Cubase 9. */ | |||
| SteinbergCubase9_5, /**< Represents Steinberg Cubase 9.5. */ | |||
| SteinbergCubase10, /**< Represents Steinberg Cubase 10. */ | |||
| SteinbergCubase10_5, /**< Represents Steinberg Cubase 10.5. */ | |||
| SteinbergCubaseGeneric, /**< Represents Steinberg Cubase. */ | |||
| SteinbergNuendo3, /**< Represents Steinberg Nuendo 3. */ | |||
| SteinbergNuendo4, /**< Represents Steinberg Nuendo 4. */ | |||
| SteinbergNuendo5, /**< Represents Steinberg Nuendo 5. */ | |||
| SteinbergNuendoGeneric, /**< Represents Steinberg Nuendo. */ | |||
| SteinbergWavelab5, /**< Represents Steinberg Wavelab 5. */ | |||
| SteinbergWavelab6, /**< Represents Steinberg Wavelab 6. */ | |||
| SteinbergWavelab7, /**< Represents Steinberg Wavelab 7. */ | |||
| SteinbergWavelab8, /**< Represents Steinberg Wavelab 8. */ | |||
| SteinbergWavelabGeneric, /**< Represents Steinberg Wavelab. */ | |||
| SteinbergTestHost, /**< Represents Steinberg's VST3 Test Host. */ | |||
| StudioOne, /**< Represents PreSonus Studio One. */ | |||
| Tracktion3, /**< Represents Tracktion 3. */ | |||
| TracktionGeneric, /**< Represents Tracktion. */ | |||
| TracktionWaveform, /**< Represents Tracktion Waveform. */ | |||
| VBVSTScanner, /**< Represents VB Audio VST Scanner. */ | |||
| ViennaEnsemblePro, /**< Represents Vienna Ensemble Pro. */ | |||
| WaveBurner /**< Represents Apple WaveBurner. */ | |||
| }; | |||
| HostType type; | |||
| //============================================================================== | |||
| /** Returns true if the host is any version of Ableton Live. */ | |||
| bool isAbletonLive() const noexcept { return type == AbletonLive6 || type == AbletonLive7 || type == AbletonLive8 | |||
| || type == AbletonLive9 || type == AbletonLive10 || type == AbletonLiveGeneric; } | |||
| /** Returns true if the host is Adobe Audition. */ | |||
| bool isAdobeAudition() const noexcept { return type == AdobeAudition; } | |||
| /** Returns true if the host is Ardour. */ | |||
| bool isArdour() const noexcept { return type == Ardour; } | |||
| /** Returns true if the host is Bitwig Studio. */ | |||
| bool isBitwigStudio() const noexcept { return type == BitwigStudio; } | |||
| /** Returns true if the host is any version of Steinberg Cubase. */ | |||
| bool isCubase() const noexcept { return type == SteinbergCubase4 || type == SteinbergCubase5 || type == SteinbergCubase5Bridged || type == SteinbergCubase6 | |||
| || type == SteinbergCubase7 || type == SteinbergCubase8 || type == SteinbergCubase8_5 || type == SteinbergCubase9 | |||
| || type == SteinbergCubase9_5 || type == SteinbergCubase10 || type == SteinbergCubase10_5 || type == SteinbergCubaseGeneric; } | |||
| /** Returns true if the host is Steinberg Cubase 7 or later. */ | |||
| bool isCubase7orLater() const noexcept { return isCubase() && ! (type == SteinbergCubase4 || type == SteinbergCubase5 || type == SteinbergCubase6); } | |||
| /** Returns true if the host is Steinberg Cubase 5 Bridged. */ | |||
| bool isCubaseBridged() const noexcept { return type == SteinbergCubase5Bridged; } | |||
| /** Returns true if the host is DaVinci Resolve. */ | |||
| bool isDaVinciResolve() const noexcept { return type == DaVinciResolve; } | |||
| /** Returns true if the host is Digital Performer. */ | |||
| bool isDigitalPerformer() const noexcept { return type == DigitalPerformer; } | |||
| /** Returns true if the host is Apple Final Cut Pro. */ | |||
| bool isFinalCut() const noexcept { return type == FinalCut; } | |||
| /** Returns true if the host is Fruity Loops. */ | |||
| bool isFruityLoops() const noexcept { return type == FruityLoops; } | |||
| /** Returns true if the host is Apple GarageBand. */ | |||
| bool isGarageBand() const noexcept { return type == AppleGarageBand; } | |||
| /** Returns true if the host is the JUCE AudioPluginHost */ | |||
| bool isJUCEPluginHost() const noexcept { return type == JUCEPluginHost; } | |||
| /** Returns true if the host is Apple Logic Pro. */ | |||
| bool isLogic() const noexcept { return type == AppleLogic; } | |||
| /** Returns true if the host is Apple MainStage. */ | |||
| bool isMainStage() const noexcept { return type == AppleMainStage; } | |||
| /** Returns true if the host is any version of Steinberg Nuendo. */ | |||
| bool isNuendo() const noexcept { return type == SteinbergNuendo3 || type == SteinbergNuendo4 || type == SteinbergNuendo5 || type == SteinbergNuendoGeneric; } | |||
| /** Returns true if the host is pluginval. */ | |||
| bool isPluginval() const noexcept { return type == pluginval; } | |||
| /** Returns true if the host is Adobe Premiere Pro. */ | |||
| bool isPremiere() const noexcept { return type == AdobePremierePro; } | |||
| /** Returns true if the host is Avid Pro Tools. */ | |||
| bool isProTools() const noexcept { return type == AvidProTools; } | |||
| /** Returns true if the host is Merging Pyramix. */ | |||
| bool isPyramix() const noexcept { return type == MergingPyramix; } | |||
| /** Returns true if the host is Muse Receptor. */ | |||
| bool isReceptor() const noexcept { return type == MuseReceptorGeneric; } | |||
| /** Returns true if the host is Cockos Reaper. */ | |||
| bool isReaper() const noexcept { return type == Reaper; } | |||
| /** Returns true if the host is Reason. */ | |||
| bool isReason() const noexcept { return type == Reason; } | |||
| /** Returns true if the host is Renoise. */ | |||
| bool isRenoise() const noexcept { return type == Renoise; } | |||
| /** Returns true if the host is SADiE. */ | |||
| bool isSADiE() const noexcept { return type == SADiE; } | |||
| /** Returns true if the host is Magix Samplitude. */ | |||
| bool isSamplitude() const noexcept { return type == MagixSamplitude; } | |||
| /** Returns true if the host is Magix Sequoia. */ | |||
| bool isSequoia() const noexcept { return type == MagixSequoia; } | |||
| /** Returns true if the host is any version of Cakewalk Sonar. */ | |||
| bool isSonar() const noexcept { return type == CakewalkSonar8 || type == CakewalkSonarGeneric || type == CakewalkByBandlab; } | |||
| /** Returns true if the host is Steinberg's VST3 Test Host. */ | |||
| bool isSteinbergTestHost() const noexcept { return type == SteinbergTestHost; } | |||
| /** Returns true if the host is any product from Steinberg. */ | |||
| bool isSteinberg() const noexcept { return isCubase() || isNuendo() || isWavelab() || isSteinbergTestHost(); } | |||
| /** Returns true if the host is PreSonus Studio One. */ | |||
| bool isStudioOne() const noexcept { return type == StudioOne; } | |||
| /** Returns true if the host is any version of Tracktion. */ | |||
| bool isTracktion() const noexcept { return type == Tracktion3 || type == TracktionGeneric || isTracktionWaveform(); } | |||
| /** Returns true if the host is Tracktion Waveform. */ | |||
| bool isTracktionWaveform() const noexcept { return type == TracktionWaveform; } | |||
| /** Returns true if the host is VB Audio VST Scanner. */ | |||
| bool isVBVSTScanner() const noexcept { return type == VBVSTScanner; } | |||
| /** Returns true if the host is Vienna Ensemble Pro. */ | |||
| bool isViennaEnsemblePro() const noexcept { return type == ViennaEnsemblePro; } | |||
| /** Returns true if the host is Apple WaveBurner. */ | |||
| bool isWaveBurner() const noexcept { return type == WaveBurner; } | |||
| /** Returns true if the host is any version of Steinberg WaveLab. */ | |||
| bool isWavelab() const noexcept { return isWavelabLegacy() || type == SteinbergWavelab7 || type == SteinbergWavelab8 || type == SteinbergWavelabGeneric; } | |||
| /** Returns true if the host is Steinberg WaveLab 6 or below. */ | |||
| bool isWavelabLegacy() const noexcept { return type == SteinbergWavelab5 || type == SteinbergWavelab6; } | |||
| //============================================================================== | |||
| /** Returns a human-readable description of the host. */ | |||
| const char* getHostDescription() const noexcept; | |||
| //============================================================================== | |||
| /** Returns true if the plugin is connected with Inter-App Audio on iOS. */ | |||
| bool isInterAppAudioConnected() const; | |||
| /** Switches to the host application when Inter-App Audio is used on iOS. */ | |||
| void switchToHostApplication() const; | |||
| /** Gets the host app's icon when Inter-App Audio is used on iOS. */ | |||
| Image getHostIcon (int size) const; | |||
| //============================================================================== | |||
| /** Returns the complete absolute path of the host application executable. */ | |||
| static String getHostPath() | |||
| { | |||
| return File::getSpecialLocation (File::hostApplicationPath).getFullPathName(); | |||
| } | |||
| //============================================================================== | |||
| /** | |||
| Returns the plug-in format via which the plug-in file was loaded. This value is | |||
| identical to AudioProcessor::wrapperType of the main audio processor of this | |||
| plug-in. This function is useful for code that does not have access to the | |||
| plug-in's main audio processor. | |||
| @see AudioProcessor::wrapperType | |||
| */ | |||
| static AudioProcessor::WrapperType getPluginLoadedAs() noexcept { return jucePlugInClientCurrentWrapperType; } | |||
| /** Returns true if the AudioProcessor instance is an AAX plug-in running in AudioSuite. */ | |||
| static bool isInAAXAudioSuite (AudioProcessor&); | |||
| //============================================================================== | |||
| #ifndef DOXYGEN | |||
| // @internal | |||
| static AudioProcessor::WrapperType jucePlugInClientCurrentWrapperType; | |||
| static std::function<bool (AudioProcessor&)> jucePlugInIsRunningInAudioSuiteFn; | |||
| static String hostIdReportedByWrapper; | |||
| #endif | |||
| private: | |||
| static HostType getHostType(); | |||
| }; | |||
| } // namespace juce | |||
| @@ -781,6 +781,8 @@ private: | |||
| if (wantsNormalise == Convolution::Normalise::yes) | |||
| normaliseImpulseResponse (resampled); | |||
| else | |||
| resampled.applyGain ((float) (originalSampleRate / processSpec.sampleRate)); | |||
| const auto currentLatency = jmax (processSpec.maximumBlockSize, (uint32) latency.latencyInSamples); | |||
| const auto maxBufferSize = shouldBeZeroLatency ? static_cast<int> (processSpec.maximumBlockSize) | |||
| @@ -514,6 +514,9 @@ public: | |||
| AudioBuffer<float> result (original.getNumChannels(), finalSize); | |||
| resamplingSource.getNextAudioBlock ({ &result, 0, result.getNumSamples() }); | |||
| result.applyGain ((float) resampleRatio); | |||
| return result; | |||
| }(); | |||
| @@ -550,10 +553,10 @@ public: | |||
| const auto ramp = makeRamp (static_cast<int> (spec.maximumBlockSize) * 8); | |||
| using BlockSize = decltype (spec.maximumBlockSize); | |||
| for (auto latency : { /*static_cast<BlockSize> (0), | |||
| for (auto latency : { static_cast<BlockSize> (0), | |||
| spec.maximumBlockSize / 3, | |||
| spec.maximumBlockSize, | |||
| spec.maximumBlockSize * 2, */ | |||
| spec.maximumBlockSize * 2, | |||
| static_cast<BlockSize> (spec.maximumBlockSize * 2.5) }) | |||
| { | |||
| testConvolution (spec, | |||
| @@ -1288,6 +1288,7 @@ PopupMenu::Options LookAndFeel_V2::getOptionsForComboBoxPopupMenu (ComboBox& box | |||
| { | |||
| return PopupMenu::Options().withTargetComponent (&box) | |||
| .withItemThatMustBeVisible (box.getSelectedId()) | |||
| .withInitiallySelectedItem (box.getSelectedId()) | |||
| .withMinimumWidth (box.getWidth()) | |||
| .withMaximumNumColumns (1) | |||
| .withStandardItemHeight (label.getHeight()); | |||
| @@ -252,12 +252,19 @@ struct MenuWindow : public Component | |||
| setOpaque (lf.findColour (PopupMenu::backgroundColourId).isOpaque() | |||
| || ! Desktop::canUseSemiTransparentWindows()); | |||
| const auto initialSelectedId = options.getInitiallySelectedItemId(); | |||
| for (int i = 0; i < menu.items.size(); ++i) | |||
| { | |||
| auto& item = menu.items.getReference (i); | |||
| if (i + 1 < menu.items.size() || ! item.isSeparator) | |||
| items.add (new ItemComponent (item, options, *this)); | |||
| { | |||
| auto* child = items.add (new ItemComponent (item, options, *this)); | |||
| if (initialSelectedId != 0 && item.itemID == initialSelectedId) | |||
| setCurrentlyHighlightedChild (child); | |||
| } | |||
| } | |||
| auto targetArea = options.getTargetScreenArea() / scaleFactor; | |||
| @@ -1239,7 +1246,7 @@ private: | |||
| { | |||
| if (globalMousePos != lastMousePos || timeNow > lastMouseMoveTime + 350) | |||
| { | |||
| const bool isMouseOver = window.reallyContains (localMousePos, true); | |||
| const auto isMouseOver = window.reallyContains (localMousePos, true); | |||
| if (isMouseOver) | |||
| window.hasBeenOver = true; | |||
| @@ -1279,7 +1286,12 @@ private: | |||
| window.activeSubMenu->hide (nullptr, true); | |||
| if (! isMouseOver) | |||
| { | |||
| if (! window.hasBeenOver) | |||
| return; | |||
| itemUnderMouse = nullptr; | |||
| } | |||
| window.setCurrentlyHighlightedChild (itemUnderMouse); | |||
| } | |||
| @@ -1751,10 +1763,16 @@ PopupMenu::Options::Options() | |||
| targetArea.setPosition (Desktop::getMousePosition()); | |||
| } | |||
| template <typename Member, typename Item> | |||
| static PopupMenu::Options with (PopupMenu::Options options, Member&& member, Item&& item) | |||
| { | |||
| options.*member = std::forward<Item> (item); | |||
| return options; | |||
| } | |||
| PopupMenu::Options PopupMenu::Options::withTargetComponent (Component* comp) const | |||
| { | |||
| Options o (*this); | |||
| o.targetComponent = comp; | |||
| auto o = with (*this, &Options::targetComponent, comp); | |||
| if (comp != nullptr) | |||
| o.targetArea = comp->getScreenBounds(); | |||
| @@ -1769,66 +1787,54 @@ PopupMenu::Options PopupMenu::Options::withTargetComponent (Component& comp) con | |||
| PopupMenu::Options PopupMenu::Options::withTargetScreenArea (Rectangle<int> area) const | |||
| { | |||
| Options o (*this); | |||
| o.targetArea = area; | |||
| return o; | |||
| return with (*this, &Options::targetArea, area); | |||
| } | |||
| PopupMenu::Options PopupMenu::Options::withDeletionCheck (Component& comp) const | |||
| { | |||
| Options o (*this); | |||
| o.componentToWatchForDeletion = ∁ | |||
| o.isWatchingForDeletion = true; | |||
| return o; | |||
| return with (with (*this, &Options::isWatchingForDeletion, true), | |||
| &Options::componentToWatchForDeletion, | |||
| &comp); | |||
| } | |||
| PopupMenu::Options PopupMenu::Options::withMinimumWidth (int w) const | |||
| { | |||
| Options o (*this); | |||
| o.minWidth = w; | |||
| return o; | |||
| return with (*this, &Options::minWidth, w); | |||
| } | |||
| PopupMenu::Options PopupMenu::Options::withMinimumNumColumns (int cols) const | |||
| { | |||
| Options o (*this); | |||
| o.minColumns = cols; | |||
| return o; | |||
| return with (*this, &Options::minColumns, cols); | |||
| } | |||
| PopupMenu::Options PopupMenu::Options::withMaximumNumColumns (int cols) const | |||
| { | |||
| Options o (*this); | |||
| o.maxColumns = cols; | |||
| return o; | |||
| return with (*this, &Options::maxColumns, cols); | |||
| } | |||
| PopupMenu::Options PopupMenu::Options::withStandardItemHeight (int height) const | |||
| { | |||
| Options o (*this); | |||
| o.standardHeight = height; | |||
| return o; | |||
| return with (*this, &Options::standardHeight, height); | |||
| } | |||
| PopupMenu::Options PopupMenu::Options::withItemThatMustBeVisible (int idOfItemToBeVisible) const | |||
| { | |||
| Options o (*this); | |||
| o.visibleItemID = idOfItemToBeVisible; | |||
| return o; | |||
| return with (*this, &Options::visibleItemID, idOfItemToBeVisible); | |||
| } | |||
| PopupMenu::Options PopupMenu::Options::withParentComponent (Component* parent) const | |||
| { | |||
| Options o (*this); | |||
| o.parentComponent = parent; | |||
| return o; | |||
| return with (*this, &Options::parentComponent, parent); | |||
| } | |||
| PopupMenu::Options PopupMenu::Options::withPreferredPopupDirection (PopupDirection direction) const | |||
| { | |||
| Options o (*this); | |||
| o.preferredPopupDirection = direction; | |||
| return o; | |||
| return with (*this, &Options::preferredPopupDirection, direction); | |||
| } | |||
| PopupMenu::Options PopupMenu::Options::withInitiallySelectedItem (int idOfItemToBeSelected) const | |||
| { | |||
| return with (*this, &Options::initiallySelectedItemId, idOfItemToBeSelected); | |||
| } | |||
| Component* PopupMenu::createWindow (const Options& options, | |||
| @@ -470,6 +470,7 @@ public: | |||
| Options withItemThatMustBeVisible (int idOfItemToBeVisible) const; | |||
| Options withParentComponent (Component* parentComponent) const; | |||
| Options withPreferredPopupDirection (PopupDirection direction) const; | |||
| Options withInitiallySelectedItem (int idOfItemToBeSelected) const; | |||
| //============================================================================== | |||
| Component* getParentComponent() const noexcept { return parentComponent; } | |||
| @@ -482,6 +483,7 @@ public: | |||
| int getStandardItemHeight() const noexcept { return standardHeight; } | |||
| int getItemThatMustBeVisible() const noexcept { return visibleItemID; } | |||
| PopupDirection getPreferredPopupDirection() const noexcept { return preferredPopupDirection; } | |||
| int getInitiallySelectedItemId() const noexcept { return initiallySelectedItemId; } | |||
| private: | |||
| //============================================================================== | |||
| @@ -489,7 +491,7 @@ public: | |||
| Component* targetComponent = nullptr; | |||
| Component* parentComponent = nullptr; | |||
| WeakReference<Component> componentToWatchForDeletion; | |||
| int visibleItemID = 0, minWidth = 0, minColumns = 1, maxColumns = 0, standardHeight = 0; | |||
| int visibleItemID = 0, minWidth = 0, minColumns = 1, maxColumns = 0, standardHeight = 0, initiallySelectedItemId = 0; | |||
| bool isWatchingForDeletion = false; | |||
| PopupDirection preferredPopupDirection = PopupDirection::downwards; | |||
| }; | |||
| @@ -41,6 +41,9 @@ public: | |||
| // it's dangerous to create a window on a thread other than the message thread. | |||
| JUCE_ASSERT_MESSAGE_MANAGER_IS_LOCKED | |||
| if (! XWindowSystem::getInstance()->isX11Available()) | |||
| return; | |||
| if (isAlwaysOnTop) | |||
| ++numAlwaysOnTopPeers; | |||
| @@ -80,8 +83,13 @@ public: | |||
| //============================================================================== | |||
| void setBounds (const Rectangle<int>& newBounds, bool isNowFullScreen) override | |||
| { | |||
| bounds = newBounds.withSize (jmax (1, newBounds.getWidth()), | |||
| jmax (1, newBounds.getHeight())); | |||
| const auto correctedNewBounds = newBounds.withSize (jmax (1, newBounds.getWidth()), | |||
| jmax (1, newBounds.getHeight())); | |||
| if (bounds == correctedNewBounds && fullScreen == isNowFullScreen) | |||
| return; | |||
| bounds = correctedNewBounds; | |||
| updateScaleFactorFromNewBounds (bounds, false); | |||
| @@ -262,12 +270,14 @@ public: | |||
| //============================================================================== | |||
| void repaint (const Rectangle<int>& area) override | |||
| { | |||
| repainter->repaint (area.getIntersection (bounds.withZeroOrigin())); | |||
| if (repainter != nullptr) | |||
| repainter->repaint (area.getIntersection (bounds.withZeroOrigin())); | |||
| } | |||
| void performAnyPendingRepaintsNow() override | |||
| { | |||
| repainter->performAnyPendingRepaintsNow(); | |||
| if (repainter != nullptr) | |||
| repainter->performAnyPendingRepaintsNow(); | |||
| } | |||
| void setIcon (const Image& newIcon) override | |||
| @@ -69,7 +69,7 @@ public: | |||
| } | |||
| } | |||
| ~Win32NativeFileChooser() | |||
| ~Win32NativeFileChooser() override | |||
| { | |||
| signalThreadShouldExit(); | |||
| waitForThreadToExit (-1); | |||
| @@ -105,7 +105,7 @@ public: | |||
| shouldCancel = true; | |||
| if (auto hwnd = nativeDialogRef.get()) | |||
| EndDialog (hwnd, 0); | |||
| PostMessage (hwnd, WM_CLOSE, 0, 0); | |||
| } | |||
| Component* getCustomComponent() { return customComponent.get(); } | |||
| @@ -237,25 +237,24 @@ private: | |||
| ScopedLock lock (owner.deletingDialog); | |||
| if (hwnd != nullptr) | |||
| if (owner.shouldCancel) | |||
| d->Close (S_FALSE); | |||
| else if (hwnd != nullptr) | |||
| owner.nativeDialogRef = hwnd; | |||
| return owner.shouldCancel ? S_FALSE : S_OK; | |||
| return S_OK; | |||
| } | |||
| JUCE_COMRESULT OnFolderChanging (IFileDialog*, IShellItem*) override { return S_OK; } | |||
| JUCE_COMRESULT OnFileOk (IFileDialog*) override { return S_OK; } | |||
| JUCE_COMRESULT OnFolderChange (IFileDialog*) override { return S_OK; } | |||
| JUCE_COMRESULT OnSelectionChange (IFileDialog*) override { return S_OK; } | |||
| JUCE_COMRESULT OnShareViolation (IFileDialog*, IShellItem*, FDE_SHAREVIOLATION_RESPONSE*) override { return S_OK; } | |||
| JUCE_COMRESULT OnOverwrite (IFileDialog*, IShellItem*, FDE_OVERWRITE_RESPONSE*) override { return S_OK; } | |||
| JUCE_COMRESULT OnFolderChanging (IFileDialog*, IShellItem*) override { return E_NOTIMPL; } | |||
| JUCE_COMRESULT OnFileOk (IFileDialog*) override { return E_NOTIMPL; } | |||
| JUCE_COMRESULT OnFolderChange (IFileDialog*) override { return E_NOTIMPL; } | |||
| JUCE_COMRESULT OnSelectionChange (IFileDialog*) override { return E_NOTIMPL; } | |||
| JUCE_COMRESULT OnShareViolation (IFileDialog*, IShellItem*, FDE_SHAREVIOLATION_RESPONSE*) override { return E_NOTIMPL; } | |||
| JUCE_COMRESULT OnOverwrite (IFileDialog*, IShellItem*, FDE_OVERWRITE_RESPONSE*) override { return E_NOTIMPL; } | |||
| Win32NativeFileChooser& owner; | |||
| }; | |||
| DWORD cookie = 0; | |||
| dialog.Advise (new Events { *this }, &cookie); | |||
| { | |||
| ScopedLock lock (deletingDialog); | |||
| @@ -263,7 +262,20 @@ private: | |||
| return false; | |||
| } | |||
| const auto result = dialog.Show (async ? nullptr : static_cast<HWND> (owner->getWindowHandle())) == S_OK; | |||
| const auto result = [&] | |||
| { | |||
| struct ScopedAdvise | |||
| { | |||
| ScopedAdvise (IFileDialog& d, Events& events) : dialog (d) { dialog.Advise (&events, &cookie); } | |||
| ~ScopedAdvise() { dialog.Unadvise (cookie); } | |||
| IFileDialog& dialog; | |||
| DWORD cookie = 0; | |||
| }; | |||
| Events events { *this }; | |||
| ScopedAdvise scope { dialog, events }; | |||
| return dialog.Show (async ? nullptr : static_cast<HWND> (owner->getWindowHandle())) == S_OK; | |||
| }(); | |||
| ScopedLock lock (deletingDialog); | |||
| nativeDialogRef = nullptr; | |||
| @@ -483,8 +495,14 @@ private: | |||
| void run() override | |||
| { | |||
| // IUnknown_GetWindow will only succeed when instantiated in a single-thread apartment | |||
| CoInitializeEx (nullptr, COINIT_APARTMENTTHREADED); | |||
| struct ScopedCoInitialize | |||
| { | |||
| // IUnknown_GetWindow will only succeed when instantiated in a single-thread apartment | |||
| ScopedCoInitialize() { CoInitializeEx (nullptr, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); } | |||
| ~ScopedCoInitialize() { CoUninitialize(); } | |||
| }; | |||
| ScopedCoInitialize scope; | |||
| auto resultsCopy = openDialog (true); | |||
| auto safeOwner = owner; | |||
| @@ -2033,7 +2033,7 @@ bool XWindowSystem::canUseARGBImages() const | |||
| X11Symbols::getInstance()->xDefaultVisual (display, X11Symbols::getInstance()->xDefaultScreen (display)), | |||
| 24, ZPixmap, nullptr, &segmentinfo, 64, 64); | |||
| canUseARGB = (testImage->bits_per_pixel == 32); | |||
| canUseARGB = testImage != nullptr && testImage->bits_per_pixel == 32; | |||
| X11Symbols::getInstance()->xDestroyImage (testImage); | |||
| } | |||
| else | |||
| @@ -3067,7 +3067,7 @@ bool XWindowSystem::initialiseXDisplay() | |||
| if (! displayVisuals->isValid()) | |||
| { | |||
| Logger::outputDebugString ("ERROR: System doesn't support 32, 24 or 16 bit RGB display.\n"); | |||
| Process::terminate(); | |||
| return false; | |||
| } | |||
| // Setup input event handler | |||
| @@ -164,6 +164,8 @@ public: | |||
| ::Display* getDisplay() { return display; } | |||
| XWindowSystemUtilities::Atoms& getAtoms() { return atoms; } | |||
| bool isX11Available() const noexcept { return xIsAvailable; } | |||
| //============================================================================== | |||
| void handleWindowMessage (LinuxComponentPeer*, XEvent&) const; | |||
| bool isParentWindowOf (::Window, ::Window possibleChild) const; | |||
| @@ -105,7 +105,7 @@ public: | |||
| XSetWindowAttributes swa; | |||
| swa.colormap = colourMap; | |||
| swa.border_pixel = 0; | |||
| swa.event_mask = ExposureMask | StructureNotifyMask; | |||
| swa.event_mask = embeddedWindowEventMask; | |||
| auto glBounds = component.getTopLevelComponent() | |||
| ->getLocalArea (&component, component.getLocalBounds()); | |||
| @@ -141,9 +141,18 @@ public: | |||
| if (embeddedWindow != 0) | |||
| { | |||
| XWindowSystemUtilities::ScopedXLock xLock; | |||
| X11Symbols::getInstance()->xUnmapWindow (display, embeddedWindow); | |||
| X11Symbols::getInstance()->xDestroyWindow (display, embeddedWindow); | |||
| X11Symbols::getInstance()->xSync (display, False); | |||
| XEvent event; | |||
| while (X11Symbols::getInstance()->xCheckWindowEvent (display, | |||
| embeddedWindow, | |||
| embeddedWindowEventMask, | |||
| &event) == True) | |||
| { | |||
| } | |||
| } | |||
| } | |||
| @@ -255,6 +264,8 @@ public: | |||
| struct Locker { Locker (NativeContext&) {} }; | |||
| private: | |||
| static constexpr int embeddedWindowEventMask = ExposureMask | StructureNotifyMask; | |||
| Component& component; | |||
| GLXContext renderContext = {}; | |||
| Window embeddedWindow = {}; | |||