@@ -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::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::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::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) | AudioChannelSet AudioChannelSet::ambisonic (int order) | ||||
{ | { | ||||
@@ -208,6 +208,18 @@ public: | |||||
*/ | */ | ||||
static AudioChannelSet JUCE_CALLTYPE create7point1point2(); | 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) | /** Creates a set for quadraphonic surround setup (left, right, leftSurround, rightSurround) | ||||
@@ -44,13 +44,20 @@ void MemoryAudioSource::releaseResources() {} | |||||
void MemoryAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill) | void MemoryAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill) | ||||
{ | { | ||||
if (buffer.getNumSamples() == 0) | |||||
{ | |||||
bufferToFill.clearActiveBufferRegion(); | |||||
return; | |||||
} | |||||
auto& dst = *bufferToFill.buffer; | auto& dst = *bufferToFill.buffer; | ||||
auto channels = jmin (dst.getNumChannels(), buffer.getNumChannels()); | 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)); | max = jmin (m - pos, n - (i % n)); | ||||
@@ -67,7 +74,7 @@ void MemoryAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& bufferT | |||||
if (pos < m) | if (pos < m) | ||||
dst.clear (bufferToFill.startSample + pos, m - pos); | dst.clear (bufferToFill.startSample + pos, m - pos); | ||||
position = (i % n); | |||||
position = i; | |||||
} | } | ||||
//============================================================================== | //============================================================================== | ||||
@@ -97,4 +104,158 @@ void MemoryAudioSource::setLooping (bool shouldLoop) | |||||
isCurrentlyLooping = 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 | } // namespace juce |
@@ -675,6 +675,19 @@ public: | |||||
return noErr; | 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; | default: break; | ||||
} | } | ||||
} | } | ||||
@@ -612,6 +612,10 @@ public: | |||||
{ | { | ||||
centreWithSize (getWidth(), getHeight()); | centreWithSize (getWidth(), getHeight()); | ||||
} | } | ||||
if (auto* processor = getAudioProcessor()) | |||||
if (auto* editor = processor->getActiveEditor()) | |||||
setResizable (editor->isResizable(), false); | |||||
#endif | #endif | ||||
} | } | ||||
@@ -927,11 +927,13 @@ public: | |||||
{ | { | ||||
if (auto* pluginInstance = getPluginInstance()) | 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 new JuceVST3Editor (*this, *pluginInstance); | ||||
} | |||||
} | } | ||||
return nullptr; | return nullptr; | ||||
@@ -126,6 +126,5 @@ | |||||
#define JUCE_STANDALONE_FILTER_WINDOW_USE_KIOSK_MODE (JUCE_IOS || JUCE_ANDROID) | #define JUCE_STANDALONE_FILTER_WINDOW_USE_KIOSK_MODE (JUCE_IOS || JUCE_ANDROID) | ||||
#endif | #endif | ||||
#include "utility/juce_PluginHostType.h" | |||||
#include "utility/juce_CreatePluginFilter.h" | #include "utility/juce_CreatePluginFilter.h" | ||||
#include "VST/juce_VSTCallbackHandler.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 | namespace juce | ||||
{ | { | ||||
AudioProcessor::WrapperType PluginHostType::jucePlugInClientCurrentWrapperType = AudioProcessor::wrapperType_Undefined; | |||||
std::function<bool (AudioProcessor&)> PluginHostType::jucePlugInIsRunningInAudioSuiteFn = nullptr; | |||||
#if JucePlugin_Build_Unity | #if JucePlugin_Build_Unity | ||||
bool juce_isRunningInUnity() { return PluginHostType::getPluginLoadedAs() == AudioProcessor::wrapperType_Unity; } | bool juce_isRunningInUnity() { return PluginHostType::getPluginLoadedAs() == AudioProcessor::wrapperType_Unity; } | ||||
#endif | #endif | ||||
@@ -146,67 +143,3 @@ std::function<bool (AudioProcessor&)> PluginHostType::jucePlugInIsRunningInAudio | |||||
#endif | #endif | ||||
} // namespace juce | } // 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 | float normaliseParamValue (float scaledValue) const noexcept | ||||
{ | { | ||||
if (discrete) | |||||
return scaledValue / (getNumSteps() - 1); | |||||
return (scaledValue - minValue) / range; | return (scaledValue - minValue) / range; | ||||
} | } | ||||
float scaleParamValue (float normalisedValue) const noexcept | float scaleParamValue (float normalisedValue) const noexcept | ||||
{ | { | ||||
if (discrete) | |||||
return normalisedValue * (getNumSteps() - 1); | |||||
return minValue + (range * normalisedValue); | 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) | if (presets != nullptr) | ||||
{ | |||||
num = (int) CFArrayGetCount (presets); | |||||
CFRelease (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 | int getCurrentProgram() override | ||||
@@ -1256,33 +1260,26 @@ public: | |||||
void setCurrentProgram (int newIndex) override | 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 | const String getProgramName (int index) override | ||||
{ | { | ||||
String s; | |||||
CFArrayRef presets; | |||||
UInt32 sz = sizeof (CFArrayRef); | |||||
if (index == -1) | if (index == -1) | ||||
{ | { | ||||
AUPreset current; | AUPreset current; | ||||
@@ -1294,27 +1291,20 @@ public: | |||||
AudioUnitGetProperty (audioUnit, kAudioUnitProperty_PresentPreset, | AudioUnitGetProperty (audioUnit, kAudioUnitProperty_PresentPreset, | ||||
kAudioUnitScope_Global, 0, ¤t, &prstsz); | 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) | 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 | void changeProgramName (int /*index*/, const String& /*newName*/) override | ||||
@@ -1471,7 +1461,7 @@ public: | |||||
info.defaultValue, | info.defaultValue, | ||||
(info.flags & kAudioUnitParameterFlag_NonRealTime) == 0, | (info.flags & kAudioUnitParameterFlag_NonRealTime) == 0, | ||||
isDiscrete, | isDiscrete, | ||||
isDiscrete ? (int) (info.maxValue + 1.0f) : AudioProcessor::getDefaultNumParameterSteps(), | |||||
isDiscrete ? (int) (info.maxValue - info.minValue + 1.0f) : AudioProcessor::getDefaultNumParameterSteps(), | |||||
isBoolean, | isBoolean, | ||||
label, | label, | ||||
(info.flags & kAudioUnitParameterFlag_ValuesHaveStrings) != 0); | (info.flags & kAudioUnitParameterFlag_ValuesHaveStrings) != 0); | ||||
@@ -266,31 +266,33 @@ static Steinberg::Vst::SpeakerArrangement getVst3SpeakerArrangement (const Audio | |||||
{ | { | ||||
using namespace Steinberg::Vst::SpeakerArr; | 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 | #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 | #endif | ||||
Steinberg::Vst::SpeakerArrangement result = 0; | Steinberg::Vst::SpeakerArrangement result = 0; | ||||
@@ -307,32 +309,36 @@ static AudioChannelSet getChannelSetForSpeakerArrangement (Steinberg::Vst::Speak | |||||
{ | { | ||||
using namespace Steinberg::Vst::SpeakerArr; | 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; | AudioChannelSet result; | ||||
@@ -253,3 +253,4 @@ struct AutoResizingNSViewComponentWithParent : public AutoResizingNSViewCompone | |||||
#include "utilities/juce_AudioParameterChoice.cpp" | #include "utilities/juce_AudioParameterChoice.cpp" | ||||
#include "utilities/juce_ParameterAttachments.cpp" | #include "utilities/juce_ParameterAttachments.cpp" | ||||
#include "utilities/juce_AudioProcessorValueTreeState.cpp" | #include "utilities/juce_AudioProcessorValueTreeState.cpp" | ||||
#include "utilities/juce_PluginHostType.cpp" |
@@ -142,3 +142,4 @@ | |||||
#include "utilities/juce_AudioParameterChoice.h" | #include "utilities/juce_AudioParameterChoice.h" | ||||
#include "utilities/juce_ParameterAttachments.h" | #include "utilities/juce_ParameterAttachments.h" | ||||
#include "utilities/juce_AudioProcessorValueTreeState.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) | if (wantsNormalise == Convolution::Normalise::yes) | ||||
normaliseImpulseResponse (resampled); | normaliseImpulseResponse (resampled); | ||||
else | |||||
resampled.applyGain ((float) (originalSampleRate / processSpec.sampleRate)); | |||||
const auto currentLatency = jmax (processSpec.maximumBlockSize, (uint32) latency.latencyInSamples); | const auto currentLatency = jmax (processSpec.maximumBlockSize, (uint32) latency.latencyInSamples); | ||||
const auto maxBufferSize = shouldBeZeroLatency ? static_cast<int> (processSpec.maximumBlockSize) | const auto maxBufferSize = shouldBeZeroLatency ? static_cast<int> (processSpec.maximumBlockSize) | ||||
@@ -514,6 +514,9 @@ public: | |||||
AudioBuffer<float> result (original.getNumChannels(), finalSize); | AudioBuffer<float> result (original.getNumChannels(), finalSize); | ||||
resamplingSource.getNextAudioBlock ({ &result, 0, result.getNumSamples() }); | resamplingSource.getNextAudioBlock ({ &result, 0, result.getNumSamples() }); | ||||
result.applyGain ((float) resampleRatio); | |||||
return result; | return result; | ||||
}(); | }(); | ||||
@@ -550,10 +553,10 @@ public: | |||||
const auto ramp = makeRamp (static_cast<int> (spec.maximumBlockSize) * 8); | const auto ramp = makeRamp (static_cast<int> (spec.maximumBlockSize) * 8); | ||||
using BlockSize = decltype (spec.maximumBlockSize); | using BlockSize = decltype (spec.maximumBlockSize); | ||||
for (auto latency : { /*static_cast<BlockSize> (0), | |||||
for (auto latency : { static_cast<BlockSize> (0), | |||||
spec.maximumBlockSize / 3, | spec.maximumBlockSize / 3, | ||||
spec.maximumBlockSize, | spec.maximumBlockSize, | ||||
spec.maximumBlockSize * 2, */ | |||||
spec.maximumBlockSize * 2, | |||||
static_cast<BlockSize> (spec.maximumBlockSize * 2.5) }) | static_cast<BlockSize> (spec.maximumBlockSize * 2.5) }) | ||||
{ | { | ||||
testConvolution (spec, | testConvolution (spec, | ||||
@@ -1288,6 +1288,7 @@ PopupMenu::Options LookAndFeel_V2::getOptionsForComboBoxPopupMenu (ComboBox& box | |||||
{ | { | ||||
return PopupMenu::Options().withTargetComponent (&box) | return PopupMenu::Options().withTargetComponent (&box) | ||||
.withItemThatMustBeVisible (box.getSelectedId()) | .withItemThatMustBeVisible (box.getSelectedId()) | ||||
.withInitiallySelectedItem (box.getSelectedId()) | |||||
.withMinimumWidth (box.getWidth()) | .withMinimumWidth (box.getWidth()) | ||||
.withMaximumNumColumns (1) | .withMaximumNumColumns (1) | ||||
.withStandardItemHeight (label.getHeight()); | .withStandardItemHeight (label.getHeight()); | ||||
@@ -252,12 +252,19 @@ struct MenuWindow : public Component | |||||
setOpaque (lf.findColour (PopupMenu::backgroundColourId).isOpaque() | setOpaque (lf.findColour (PopupMenu::backgroundColourId).isOpaque() | ||||
|| ! Desktop::canUseSemiTransparentWindows()); | || ! Desktop::canUseSemiTransparentWindows()); | ||||
const auto initialSelectedId = options.getInitiallySelectedItemId(); | |||||
for (int i = 0; i < menu.items.size(); ++i) | for (int i = 0; i < menu.items.size(); ++i) | ||||
{ | { | ||||
auto& item = menu.items.getReference (i); | auto& item = menu.items.getReference (i); | ||||
if (i + 1 < menu.items.size() || ! item.isSeparator) | 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; | auto targetArea = options.getTargetScreenArea() / scaleFactor; | ||||
@@ -1239,7 +1246,7 @@ private: | |||||
{ | { | ||||
if (globalMousePos != lastMousePos || timeNow > lastMouseMoveTime + 350) | if (globalMousePos != lastMousePos || timeNow > lastMouseMoveTime + 350) | ||||
{ | { | ||||
const bool isMouseOver = window.reallyContains (localMousePos, true); | |||||
const auto isMouseOver = window.reallyContains (localMousePos, true); | |||||
if (isMouseOver) | if (isMouseOver) | ||||
window.hasBeenOver = true; | window.hasBeenOver = true; | ||||
@@ -1279,7 +1286,12 @@ private: | |||||
window.activeSubMenu->hide (nullptr, true); | window.activeSubMenu->hide (nullptr, true); | ||||
if (! isMouseOver) | if (! isMouseOver) | ||||
{ | |||||
if (! window.hasBeenOver) | |||||
return; | |||||
itemUnderMouse = nullptr; | itemUnderMouse = nullptr; | ||||
} | |||||
window.setCurrentlyHighlightedChild (itemUnderMouse); | window.setCurrentlyHighlightedChild (itemUnderMouse); | ||||
} | } | ||||
@@ -1751,10 +1763,16 @@ PopupMenu::Options::Options() | |||||
targetArea.setPosition (Desktop::getMousePosition()); | 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 | PopupMenu::Options PopupMenu::Options::withTargetComponent (Component* comp) const | ||||
{ | { | ||||
Options o (*this); | |||||
o.targetComponent = comp; | |||||
auto o = with (*this, &Options::targetComponent, comp); | |||||
if (comp != nullptr) | if (comp != nullptr) | ||||
o.targetArea = comp->getScreenBounds(); | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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, | Component* PopupMenu::createWindow (const Options& options, | ||||
@@ -470,6 +470,7 @@ public: | |||||
Options withItemThatMustBeVisible (int idOfItemToBeVisible) const; | Options withItemThatMustBeVisible (int idOfItemToBeVisible) const; | ||||
Options withParentComponent (Component* parentComponent) const; | Options withParentComponent (Component* parentComponent) const; | ||||
Options withPreferredPopupDirection (PopupDirection direction) const; | Options withPreferredPopupDirection (PopupDirection direction) const; | ||||
Options withInitiallySelectedItem (int idOfItemToBeSelected) const; | |||||
//============================================================================== | //============================================================================== | ||||
Component* getParentComponent() const noexcept { return parentComponent; } | Component* getParentComponent() const noexcept { return parentComponent; } | ||||
@@ -482,6 +483,7 @@ public: | |||||
int getStandardItemHeight() const noexcept { return standardHeight; } | int getStandardItemHeight() const noexcept { return standardHeight; } | ||||
int getItemThatMustBeVisible() const noexcept { return visibleItemID; } | int getItemThatMustBeVisible() const noexcept { return visibleItemID; } | ||||
PopupDirection getPreferredPopupDirection() const noexcept { return preferredPopupDirection; } | PopupDirection getPreferredPopupDirection() const noexcept { return preferredPopupDirection; } | ||||
int getInitiallySelectedItemId() const noexcept { return initiallySelectedItemId; } | |||||
private: | private: | ||||
//============================================================================== | //============================================================================== | ||||
@@ -489,7 +491,7 @@ public: | |||||
Component* targetComponent = nullptr; | Component* targetComponent = nullptr; | ||||
Component* parentComponent = nullptr; | Component* parentComponent = nullptr; | ||||
WeakReference<Component> componentToWatchForDeletion; | 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; | bool isWatchingForDeletion = false; | ||||
PopupDirection preferredPopupDirection = PopupDirection::downwards; | PopupDirection preferredPopupDirection = PopupDirection::downwards; | ||||
}; | }; | ||||
@@ -41,6 +41,9 @@ public: | |||||
// it's dangerous to create a window on a thread other than the message thread. | // it's dangerous to create a window on a thread other than the message thread. | ||||
JUCE_ASSERT_MESSAGE_MANAGER_IS_LOCKED | JUCE_ASSERT_MESSAGE_MANAGER_IS_LOCKED | ||||
if (! XWindowSystem::getInstance()->isX11Available()) | |||||
return; | |||||
if (isAlwaysOnTop) | if (isAlwaysOnTop) | ||||
++numAlwaysOnTopPeers; | ++numAlwaysOnTopPeers; | ||||
@@ -80,8 +83,13 @@ public: | |||||
//============================================================================== | //============================================================================== | ||||
void setBounds (const Rectangle<int>& newBounds, bool isNowFullScreen) override | 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); | updateScaleFactorFromNewBounds (bounds, false); | ||||
@@ -262,12 +270,14 @@ public: | |||||
//============================================================================== | //============================================================================== | ||||
void repaint (const Rectangle<int>& area) override | 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 | void performAnyPendingRepaintsNow() override | ||||
{ | { | ||||
repainter->performAnyPendingRepaintsNow(); | |||||
if (repainter != nullptr) | |||||
repainter->performAnyPendingRepaintsNow(); | |||||
} | } | ||||
void setIcon (const Image& newIcon) override | void setIcon (const Image& newIcon) override | ||||
@@ -69,7 +69,7 @@ public: | |||||
} | } | ||||
} | } | ||||
~Win32NativeFileChooser() | |||||
~Win32NativeFileChooser() override | |||||
{ | { | ||||
signalThreadShouldExit(); | signalThreadShouldExit(); | ||||
waitForThreadToExit (-1); | waitForThreadToExit (-1); | ||||
@@ -105,7 +105,7 @@ public: | |||||
shouldCancel = true; | shouldCancel = true; | ||||
if (auto hwnd = nativeDialogRef.get()) | if (auto hwnd = nativeDialogRef.get()) | ||||
EndDialog (hwnd, 0); | |||||
PostMessage (hwnd, WM_CLOSE, 0, 0); | |||||
} | } | ||||
Component* getCustomComponent() { return customComponent.get(); } | Component* getCustomComponent() { return customComponent.get(); } | ||||
@@ -237,25 +237,24 @@ private: | |||||
ScopedLock lock (owner.deletingDialog); | ScopedLock lock (owner.deletingDialog); | ||||
if (hwnd != nullptr) | |||||
if (owner.shouldCancel) | |||||
d->Close (S_FALSE); | |||||
else if (hwnd != nullptr) | |||||
owner.nativeDialogRef = hwnd; | 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; | Win32NativeFileChooser& owner; | ||||
}; | }; | ||||
DWORD cookie = 0; | |||||
dialog.Advise (new Events { *this }, &cookie); | |||||
{ | { | ||||
ScopedLock lock (deletingDialog); | ScopedLock lock (deletingDialog); | ||||
@@ -263,7 +262,20 @@ private: | |||||
return false; | 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); | ScopedLock lock (deletingDialog); | ||||
nativeDialogRef = nullptr; | nativeDialogRef = nullptr; | ||||
@@ -483,8 +495,14 @@ private: | |||||
void run() override | 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 resultsCopy = openDialog (true); | ||||
auto safeOwner = owner; | auto safeOwner = owner; | ||||
@@ -2033,7 +2033,7 @@ bool XWindowSystem::canUseARGBImages() const | |||||
X11Symbols::getInstance()->xDefaultVisual (display, X11Symbols::getInstance()->xDefaultScreen (display)), | X11Symbols::getInstance()->xDefaultVisual (display, X11Symbols::getInstance()->xDefaultScreen (display)), | ||||
24, ZPixmap, nullptr, &segmentinfo, 64, 64); | 24, ZPixmap, nullptr, &segmentinfo, 64, 64); | ||||
canUseARGB = (testImage->bits_per_pixel == 32); | |||||
canUseARGB = testImage != nullptr && testImage->bits_per_pixel == 32; | |||||
X11Symbols::getInstance()->xDestroyImage (testImage); | X11Symbols::getInstance()->xDestroyImage (testImage); | ||||
} | } | ||||
else | else | ||||
@@ -3067,7 +3067,7 @@ bool XWindowSystem::initialiseXDisplay() | |||||
if (! displayVisuals->isValid()) | if (! displayVisuals->isValid()) | ||||
{ | { | ||||
Logger::outputDebugString ("ERROR: System doesn't support 32, 24 or 16 bit RGB display.\n"); | Logger::outputDebugString ("ERROR: System doesn't support 32, 24 or 16 bit RGB display.\n"); | ||||
Process::terminate(); | |||||
return false; | |||||
} | } | ||||
// Setup input event handler | // Setup input event handler | ||||
@@ -164,6 +164,8 @@ public: | |||||
::Display* getDisplay() { return display; } | ::Display* getDisplay() { return display; } | ||||
XWindowSystemUtilities::Atoms& getAtoms() { return atoms; } | XWindowSystemUtilities::Atoms& getAtoms() { return atoms; } | ||||
bool isX11Available() const noexcept { return xIsAvailable; } | |||||
//============================================================================== | //============================================================================== | ||||
void handleWindowMessage (LinuxComponentPeer*, XEvent&) const; | void handleWindowMessage (LinuxComponentPeer*, XEvent&) const; | ||||
bool isParentWindowOf (::Window, ::Window possibleChild) const; | bool isParentWindowOf (::Window, ::Window possibleChild) const; | ||||
@@ -105,7 +105,7 @@ public: | |||||
XSetWindowAttributes swa; | XSetWindowAttributes swa; | ||||
swa.colormap = colourMap; | swa.colormap = colourMap; | ||||
swa.border_pixel = 0; | swa.border_pixel = 0; | ||||
swa.event_mask = ExposureMask | StructureNotifyMask; | |||||
swa.event_mask = embeddedWindowEventMask; | |||||
auto glBounds = component.getTopLevelComponent() | auto glBounds = component.getTopLevelComponent() | ||||
->getLocalArea (&component, component.getLocalBounds()); | ->getLocalArea (&component, component.getLocalBounds()); | ||||
@@ -141,9 +141,18 @@ public: | |||||
if (embeddedWindow != 0) | if (embeddedWindow != 0) | ||||
{ | { | ||||
XWindowSystemUtilities::ScopedXLock xLock; | XWindowSystemUtilities::ScopedXLock xLock; | ||||
X11Symbols::getInstance()->xUnmapWindow (display, embeddedWindow); | X11Symbols::getInstance()->xUnmapWindow (display, embeddedWindow); | ||||
X11Symbols::getInstance()->xDestroyWindow (display, embeddedWindow); | X11Symbols::getInstance()->xDestroyWindow (display, embeddedWindow); | ||||
X11Symbols::getInstance()->xSync (display, False); | 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&) {} }; | struct Locker { Locker (NativeContext&) {} }; | ||||
private: | private: | ||||
static constexpr int embeddedWindowEventMask = ExposureMask | StructureNotifyMask; | |||||
Component& component; | Component& component; | ||||
GLXContext renderContext = {}; | GLXContext renderContext = {}; | ||||
Window embeddedWindow = {}; | Window embeddedWindow = {}; | ||||