Browse Source

Delete juce_audio_processors

tags/1.9.8
falkTX 7 years ago
parent
commit
b1a15e0cd6
48 changed files with 0 additions and 22719 deletions
  1. +0
    -135
      source/modules/juce_audio_processors/Makefile
  2. +0
    -214
      source/modules/juce_audio_processors/format/juce_AudioPluginFormat.cpp
  3. +0
    -168
      source/modules/juce_audio_processors/format/juce_AudioPluginFormat.h
  4. +0
    -183
      source/modules/juce_audio_processors/format/juce_AudioPluginFormatManager.cpp
  5. +0
    -138
      source/modules/juce_audio_processors/format/juce_AudioPluginFormatManager.h
  6. +0
    -535
      source/modules/juce_audio_processors/format_types/juce_AU_Shared.h
  7. +0
    -79
      source/modules/juce_audio_processors/format_types/juce_AudioUnitPluginFormat.h
  8. +0
    -2463
      source/modules/juce_audio_processors/format_types/juce_AudioUnitPluginFormat.mm
  9. +0
    -718
      source/modules/juce_audio_processors/format_types/juce_LADSPAPluginFormat.cpp
  10. +0
    -70
      source/modules/juce_audio_processors/format_types/juce_LADSPAPluginFormat.h
  11. +0
    -633
      source/modules/juce_audio_processors/format_types/juce_VST3Common.h
  12. +0
    -186
      source/modules/juce_audio_processors/format_types/juce_VST3Headers.h
  13. +0
    -2983
      source/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp
  14. +0
    -71
      source/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.h
  15. +0
    -298
      source/modules/juce_audio_processors/format_types/juce_VSTCommon.h
  16. +0
    -485
      source/modules/juce_audio_processors/format_types/juce_VSTInterface.h
  17. +0
    -191
      source/modules/juce_audio_processors/format_types/juce_VSTMidiEventList.h
  18. +0
    -2972
      source/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp
  19. +0
    -132
      source/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.h
  20. +0
    -185
      source/modules/juce_audio_processors/juce_audio_processors.cpp
  21. +0
    -124
      source/modules/juce_audio_processors/juce_audio_processors.h
  22. +0
    -89
      source/modules/juce_audio_processors/processors/juce_AudioPluginInstance.h
  23. +0
    -1464
      source/modules/juce_audio_processors/processors/juce_AudioProcessor.cpp
  24. +0
    -1641
      source/modules/juce_audio_processors/processors/juce_AudioProcessor.h
  25. +0
    -189
      source/modules/juce_audio_processors/processors/juce_AudioProcessorEditor.cpp
  26. +0
    -209
      source/modules/juce_audio_processors/processors/juce_AudioProcessorEditor.h
  27. +0
    -1702
      source/modules/juce_audio_processors/processors/juce_AudioProcessorGraph.cpp
  28. +0
    -411
      source/modules/juce_audio_processors/processors/juce_AudioProcessorGraph.h
  29. +0
    -107
      source/modules/juce_audio_processors/processors/juce_AudioProcessorListener.h
  30. +0
    -197
      source/modules/juce_audio_processors/processors/juce_AudioProcessorParameter.h
  31. +0
    -192
      source/modules/juce_audio_processors/processors/juce_GenericAudioProcessorEditor.cpp
  32. +0
    -58
      source/modules/juce_audio_processors/processors/juce_GenericAudioProcessorEditor.h
  33. +0
    -151
      source/modules/juce_audio_processors/processors/juce_PluginDescription.cpp
  34. +0
    -156
      source/modules/juce_audio_processors/processors/juce_PluginDescription.h
  35. +0
    -587
      source/modules/juce_audio_processors/scanning/juce_KnownPluginList.cpp
  36. +0
    -225
      source/modules/juce_audio_processors/scanning/juce_KnownPluginList.h
  37. +0
    -136
      source/modules/juce_audio_processors/scanning/juce_PluginDirectoryScanner.cpp
  38. +0
    -131
      source/modules/juce_audio_processors/scanning/juce_PluginDirectoryScanner.h
  39. +0
    -593
      source/modules/juce_audio_processors/scanning/juce_PluginListComponent.cpp
  40. +0
    -132
      source/modules/juce_audio_processors/scanning/juce_PluginListComponent.h
  41. +0
    -71
      source/modules/juce_audio_processors/utilities/juce_AudioParameterBool.h
  42. +0
    -86
      source/modules/juce_audio_processors/utilities/juce_AudioParameterChoice.h
  43. +0
    -87
      source/modules/juce_audio_processors/utilities/juce_AudioParameterFloat.h
  44. +0
    -84
      source/modules/juce_audio_processors/utilities/juce_AudioParameterInt.h
  45. +0
    -69
      source/modules/juce_audio_processors/utilities/juce_AudioProcessorParameterWithID.h
  46. +0
    -175
      source/modules/juce_audio_processors/utilities/juce_AudioProcessorParameters.cpp
  47. +0
    -576
      source/modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.cpp
  48. +0
    -238
      source/modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.h

+ 0
- 135
source/modules/juce_audio_processors/Makefile View File

@@ -1,135 +0,0 @@
#!/usr/bin/make -f
# Makefile for juce_audio_processors #
# ---------------------------------- #
# Created by falkTX
#

CWD=../..
MODULENAME=juce_audio_processors
include ../Makefile.mk

# ----------------------------------------------------------------------------------------------------------------------------

BUILD_CXX_FLAGS += $(JUCE_AUDIO_PROCESSORS_FLAGS) -I$(CWD)/includes/ladspa -I$(CWD)/includes/vst2 -I$(CWD)/includes/vst3 -I..

ifeq ($(CARLA_VESTIGE_HEADER),true)
BUILD_CXX_FLAGS += -DVESTIGE_HEADER
else
# needed by vst3
BUILD_CXX_FLAGS += -w
ifeq ($(DEBUG),true)
BUILD_CXX_FLAGS += -DDEVELOPMENT -D_DEBUG
else
BUILD_CXX_FLAGS += -DRELEASE
endif
# needed by vst3 on mingw
ifeq ($(WIN32),true)
BUILD_CXX_FLAGS += -D_NATIVE_WCHAR_T_DEFINED -D__wchar_t=wchar_t -fpermissive
endif
endif

# ----------------------------------------------------------------------------------------------------------------------------

ifeq ($(MACOS),true)
OBJS = $(OBJDIR)/$(MODULENAME).mm.o
OBJS_posix32 = $(OBJDIR)/$(MODULENAME).mm.posix32.o
OBJS_posix64 = $(OBJDIR)/$(MODULENAME).mm.posix64.o
else
OBJS = $(OBJDIR)/$(MODULENAME).cpp.o
OBJS_posix32 = $(OBJDIR)/$(MODULENAME).cpp.posix32.o
OBJS_posix64 = $(OBJDIR)/$(MODULENAME).cpp.posix64.o
endif
OBJS_win32 = $(OBJDIR)/$(MODULENAME).cpp.win32.o
OBJS_win64 = $(OBJDIR)/$(MODULENAME).cpp.win64.o

# ----------------------------------------------------------------------------------------------------------------------------

all: $(MODULEDIR)/$(MODULENAME).a
posix32: $(MODULEDIR)/$(MODULENAME).posix32.a
posix64: $(MODULEDIR)/$(MODULENAME).posix64.a
win32: $(MODULEDIR)/$(MODULENAME).win32.a
win64: $(MODULEDIR)/$(MODULENAME).win64.a

# ----------------------------------------------------------------------------------------------------------------------------

clean:
rm -f $(OBJDIR)/*.o $(MODULEDIR)/$(MODULENAME)*.a

debug:
$(MAKE) DEBUG=true

# ----------------------------------------------------------------------------------------------------------------------------

$(MODULEDIR)/$(MODULENAME).a: $(OBJS)
-@mkdir -p $(MODULEDIR)
@echo "Creating $(MODULENAME).a"
@rm -f $@
@$(AR) crs $@ $^

$(MODULEDIR)/$(MODULENAME).posix32.a: $(OBJS_posix32)
-@mkdir -p $(MODULEDIR)
@echo "Creating $(MODULENAME).posix32.a"
@rm -f $@
@$(AR) crs $@ $^

$(MODULEDIR)/$(MODULENAME).posix64.a: $(OBJS_posix64)
-@mkdir -p $(MODULEDIR)
@echo "Creating $(MODULENAME).posix64.a"
@rm -f $@
@$(AR) crs $@ $^

$(MODULEDIR)/$(MODULENAME).win32.a: $(OBJS_win32)
-@mkdir -p $(MODULEDIR)
@echo "Creating $(MODULENAME).win32.a"
@rm -f $@
@$(AR) crs $@ $^

$(MODULEDIR)/$(MODULENAME).win64.a: $(OBJS_win64)
-@mkdir -p $(MODULEDIR)
@echo "Creating $(MODULENAME).win64.a"
@rm -f $@
@$(AR) crs $@ $^

# ----------------------------------------------------------------------------------------------------------------------------

$(OBJDIR)/$(MODULENAME).cpp.o: $(MODULENAME).cpp
-@mkdir -p $(OBJDIR)
@echo "Compiling $<"
@$(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@

$(OBJDIR)/$(MODULENAME).cpp.%32.o: $(MODULENAME).cpp
-@mkdir -p $(OBJDIR)
@echo "Compiling $< (32bit)"
@$(CXX) $< $(BUILD_CXX_FLAGS) $(32BIT_FLAGS) -c -o $@

$(OBJDIR)/$(MODULENAME).cpp.%64.o: $(MODULENAME).cpp
-@mkdir -p $(OBJDIR)
@echo "Compiling $< (64bit)"
@$(CXX) $< $(BUILD_CXX_FLAGS) $(64BIT_FLAGS) -c -o $@

# ----------------------------------------------------------------------------------------------------------------------------

$(OBJDIR)/$(MODULENAME).mm.o: $(MODULENAME).cpp
-@mkdir -p $(OBJDIR)
@echo "Compiling $<"
@$(CXX) $< $(BUILD_CXX_FLAGS) -ObjC++ -c -o $@

$(OBJDIR)/$(MODULENAME).mm.%32.o: $(MODULENAME).cpp
-@mkdir -p $(OBJDIR)
@echo "Compiling $< (32bit)"
@$(CXX) $< $(BUILD_CXX_FLAGS) $(32BIT_FLAGS) -ObjC++ -c -o $@

$(OBJDIR)/$(MODULENAME).mm.%64.o: $(MODULENAME).cpp
-@mkdir -p $(OBJDIR)
@echo "Compiling $< (64bit)"
@$(CXX) $< $(BUILD_CXX_FLAGS) $(64BIT_FLAGS) -ObjC++ -c -o $@

# ----------------------------------------------------------------------------------------------------------------------------

-include $(OBJS:%.o=%.d)
-include $(OBJS_posix32:%.o=%.d)
-include $(OBJS_posix64:%.o=%.d)
-include $(OBJS_win32:%.o=%.d)
-include $(OBJS_win64:%.o=%.d)

# ----------------------------------------------------------------------------------------------------------------------------

+ 0
- 214
source/modules/juce_audio_processors/format/juce_AudioPluginFormat.cpp View File

@@ -1,214 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
namespace AudioPluginFormatHelpers
{
struct CallbackInvoker
{
struct InvokeOnMessageThread : public CallbackMessage
{
InvokeOnMessageThread (AudioPluginInstance* inInstance, const String& inError,
AudioPluginFormat::InstantiationCompletionCallback* inCompletion,
CallbackInvoker* invoker)
: instance (inInstance), error (inError), compCallback (inCompletion), owner (invoker)
{}
void messageCallback() override { compCallback->completionCallback (instance, error); }
//==============================================================================
AudioPluginInstance* instance;
String error;
ScopedPointer<AudioPluginFormat::InstantiationCompletionCallback> compCallback;
ScopedPointer<CallbackInvoker> owner;
};
//==============================================================================
CallbackInvoker (AudioPluginFormat::InstantiationCompletionCallback* cc) : completion (cc)
{}
void completionCallback (AudioPluginInstance* instance, const String& error)
{
(new InvokeOnMessageThread (instance, error, completion, this))->post();
}
static void staticCompletionCallback (void* userData, AudioPluginInstance* instance, const String& error)
{
reinterpret_cast<CallbackInvoker*> (userData)->completionCallback (instance, error);
}
//==============================================================================
AudioPluginFormat::InstantiationCompletionCallback* completion;
};
}
AudioPluginFormat::AudioPluginFormat() noexcept {}
AudioPluginFormat::~AudioPluginFormat() {}
AudioPluginInstance* AudioPluginFormat::createInstanceFromDescription (const PluginDescription& desc,
double initialSampleRate,
int initialBufferSize)
{
String errorMessage;
return createInstanceFromDescription (desc, initialSampleRate, initialBufferSize, errorMessage);
}
//==============================================================================
struct EventSignaler : public AudioPluginFormat::InstantiationCompletionCallback
{
EventSignaler (WaitableEvent& inEvent, AudioPluginInstance*& inInstance, String& inErrorMessage)
: event (inEvent), outInstance (inInstance), outErrorMessage (inErrorMessage)
{}
void completionCallback (AudioPluginInstance* newInstance, const String& result) override
{
outInstance = newInstance;
outErrorMessage = result;
event.signal();
}
static void staticCompletionCallback (void* userData, AudioPluginInstance* pluginInstance, const String& error)
{
reinterpret_cast<EventSignaler*> (userData)->completionCallback (pluginInstance, error);
}
WaitableEvent& event;
AudioPluginInstance*& outInstance;
String& outErrorMessage;
JUCE_DECLARE_NON_COPYABLE (EventSignaler)
};
AudioPluginInstance* AudioPluginFormat::createInstanceFromDescription (const PluginDescription& desc,
double initialSampleRate,
int initialBufferSize,
String& errorMessage)
{
if (MessageManager::getInstance()->isThisTheMessageThread()
&& requiresUnblockedMessageThreadDuringCreation(desc))
{
errorMessage = NEEDS_TRANS ("This plug-in cannot be instantiated synchronously");
return nullptr;
}
WaitableEvent waitForCreation;
AudioPluginInstance* instance = nullptr;
ScopedPointer<EventSignaler> eventSignaler (new EventSignaler (waitForCreation, instance, errorMessage));
if (! MessageManager::getInstance()->isThisTheMessageThread())
createPluginInstanceAsync (desc, initialSampleRate, initialBufferSize, eventSignaler.release());
else
createPluginInstance (desc, initialSampleRate, initialBufferSize,
eventSignaler, EventSignaler::staticCompletionCallback);
waitForCreation.wait();
return instance;
}
void AudioPluginFormat::createPluginInstanceAsync (const PluginDescription& description,
double initialSampleRate,
int initialBufferSize,
AudioPluginFormat::InstantiationCompletionCallback* callback)
{
if (MessageManager::getInstance()->isThisTheMessageThread())
{
createPluginInstanceOnMessageThread (description, initialSampleRate, initialBufferSize, callback);
return;
}
//==============================================================================
struct InvokeOnMessageThread : public CallbackMessage
{
InvokeOnMessageThread (AudioPluginFormat* myself,
const PluginDescription& descriptionParam,
double initialSampleRateParam,
int initialBufferSizeParam,
AudioPluginFormat::InstantiationCompletionCallback* callbackParam)
: owner (myself), descr (descriptionParam), sampleRate (initialSampleRateParam),
bufferSize (initialBufferSizeParam), call (callbackParam)
{}
void messageCallback() override
{
owner->createPluginInstanceOnMessageThread (descr, sampleRate, bufferSize, call);
}
AudioPluginFormat* owner;
PluginDescription descr;
double sampleRate;
int bufferSize;
AudioPluginFormat::InstantiationCompletionCallback* call;
};
(new InvokeOnMessageThread (this, description, initialSampleRate, initialBufferSize, callback))->post();
}
void AudioPluginFormat::createPluginInstanceAsync (const PluginDescription& description,
double initialSampleRate,
int initialBufferSize,
std::function<void (AudioPluginInstance*, const String&)> f)
{
struct CallbackInvoker : public AudioPluginFormat::InstantiationCompletionCallback
{
CallbackInvoker (std::function<void (AudioPluginInstance*, const String&)> inCompletion)
: completion (inCompletion)
{}
void completionCallback (AudioPluginInstance* instance, const String& error) override
{
completion (instance, error);
}
std::function<void (AudioPluginInstance*, const String&)> completion;
};
createPluginInstanceAsync (description, initialSampleRate, initialBufferSize, new CallbackInvoker (f));
}
void AudioPluginFormat::createPluginInstanceOnMessageThread (const PluginDescription& description,
double initialSampleRate,
int initialBufferSize,
AudioPluginFormat::InstantiationCompletionCallback* callback)
{
jassert (callback != nullptr);
jassert (MessageManager::getInstance()->isThisTheMessageThread());
//==============================================================================
//==============================================================================
AudioPluginFormatHelpers::CallbackInvoker* completion = new AudioPluginFormatHelpers::CallbackInvoker (callback);
createPluginInstance (description, initialSampleRate, initialBufferSize, completion,
AudioPluginFormatHelpers::CallbackInvoker::staticCompletionCallback);
}
} // namespace juce

+ 0
- 168
source/modules/juce_audio_processors/format/juce_AudioPluginFormat.h View File

@@ -1,168 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
The base class for a type of plugin format, such as VST, AudioUnit, LADSPA, etc.
@see AudioPluginFormatManager
*/
class JUCE_API AudioPluginFormat
{
public:
//==============================================================================
struct JUCE_API InstantiationCompletionCallback
{
virtual ~InstantiationCompletionCallback() {}
virtual void completionCallback (AudioPluginInstance* instance, const String& error) = 0;
JUCE_LEAK_DETECTOR (InstantiationCompletionCallback)
};
//==============================================================================
/** Destructor. */
virtual ~AudioPluginFormat();
//==============================================================================
/** Returns the format name.
E.g. "VST", "AudioUnit", etc.
*/
virtual String getName() const = 0;
/** This tries to create descriptions for all the plugin types available in
a binary module file.
The file will be some kind of DLL or bundle.
Normally there will only be one type returned, but some plugins
(e.g. VST shells) can use a single DLL to create a set of different plugin
subtypes, so in that case, each subtype is returned as a separate object.
*/
virtual void findAllTypesForFile (OwnedArray<PluginDescription>& results,
const String& fileOrIdentifier) = 0;
/** Tries to recreate a type from a previously generated PluginDescription.
@see AudioPluginFormatManager::createInstance
*/
AudioPluginInstance* createInstanceFromDescription (const PluginDescription&,
double initialSampleRate,
int initialBufferSize);
/** Same as above but with the possibility of returning an error message.
@see AudioPluginFormatManager::createInstance
*/
AudioPluginInstance* createInstanceFromDescription (const PluginDescription&,
double initialSampleRate,
int initialBufferSize,
String& errorMessage);
/** Tries to recreate a type from a previously generated PluginDescription.
@see AudioPluginFormatManager::createInstanceAsync
*/
void createPluginInstanceAsync (const PluginDescription& description,
double initialSampleRate,
int initialBufferSize,
InstantiationCompletionCallback* completionCallback);
void createPluginInstanceAsync (const PluginDescription& description,
double initialSampleRate,
int initialBufferSize,
std::function<void (AudioPluginInstance*, const String&)> completionCallback);
/** Should do a quick check to see if this file or directory might be a plugin of
this format.
This is for searching for potential files, so it shouldn't actually try to
load the plugin or do anything time-consuming.
*/
virtual bool fileMightContainThisPluginType (const String& fileOrIdentifier) = 0;
/** Returns a readable version of the name of the plugin that this identifier refers to. */
virtual String getNameOfPluginFromIdentifier (const String& fileOrIdentifier) = 0;
/** Returns true if this plugin's version or date has changed and it should be re-checked. */
virtual bool pluginNeedsRescanning (const PluginDescription&) = 0;
/** Checks whether this plugin could possibly be loaded.
It doesn't actually need to load it, just to check whether the file or component
still exists.
*/
virtual bool doesPluginStillExist (const PluginDescription&) = 0;
/** Returns true if this format needs to run a scan to find its list of plugins. */
virtual bool canScanForPlugins() const = 0;
/** Searches a suggested set of directories for any plugins in this format.
The path might be ignored, e.g. by AUs, which are found by the OS rather
than manually.
@param directoriesToSearch This specifies which directories shall be
searched for plug-ins.
@param recursive Should the search recursively traverse folders.
@param allowPluginsWhichRequireAsynchronousInstantiation
If this is false then plug-ins which require
asynchronous creation will be excluded.
*/
virtual StringArray searchPathsForPlugins (const FileSearchPath& directoriesToSearch,
bool recursive,
bool allowPluginsWhichRequireAsynchronousInstantiation = false) = 0;
/** Returns the typical places to look for this kind of plugin.
Note that if this returns no paths, it means that the format doesn't search in
files or folders, e.g. AudioUnits.
*/
virtual FileSearchPath getDefaultLocationsToSearch() = 0;
protected:
//==============================================================================
friend class AudioPluginFormatManager;
AudioPluginFormat() noexcept;
/** Implementors must override this function. This is guaranteed to be called on
the message thread. You may call the callback on any thread.
*/
virtual void createPluginInstance (const PluginDescription&, double initialSampleRate,
int initialBufferSize, void* userData,
void (*callback) (void*, AudioPluginInstance*, const String&)) = 0;
virtual bool requiresUnblockedMessageThreadDuringCreation (const PluginDescription&) const noexcept = 0;
private:
/** @internal */
void createPluginInstanceOnMessageThread (const PluginDescription&, double rate, int size,
AudioPluginFormat::InstantiationCompletionCallback*);
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioPluginFormat)
};
} // namespace juce

+ 0
- 183
source/modules/juce_audio_processors/format/juce_AudioPluginFormatManager.cpp View File

@@ -1,183 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
namespace PluginFormatManagerHelpers
{
struct ErrorCallbackOnMessageThread : public CallbackMessage
{
ErrorCallbackOnMessageThread (const String& inError,
AudioPluginFormat::InstantiationCompletionCallback* inCallback)
: error (inError), callback (inCallback)
{
}
void messageCallback() override { callback->completionCallback (nullptr, error); }
String error;
ScopedPointer<AudioPluginFormat::InstantiationCompletionCallback> callback;
};
struct ErrorLambdaOnMessageThread : public CallbackMessage
{
ErrorLambdaOnMessageThread (const String& inError,
std::function<void (AudioPluginInstance*, const String&)> f)
: error (inError), lambda (f)
{
}
void messageCallback() override { lambda (nullptr, error); }
String error;
std::function<void (AudioPluginInstance*, const String&)> lambda;
};
}
AudioPluginFormatManager::AudioPluginFormatManager() {}
AudioPluginFormatManager::~AudioPluginFormatManager() {}
//==============================================================================
void AudioPluginFormatManager::addDefaultFormats()
{
#if JUCE_DEBUG
// you should only call this method once!
for (int i = formats.size(); --i >= 0;)
{
#if JUCE_PLUGINHOST_VST && (JUCE_MAC || JUCE_WINDOWS || JUCE_LINUX || JUCE_IOS)
jassert (dynamic_cast<VSTPluginFormat*> (formats[i]) == nullptr);
#endif
#if JUCE_PLUGINHOST_VST3 && (JUCE_MAC || JUCE_WINDOWS)
jassert (dynamic_cast<VST3PluginFormat*> (formats[i]) == nullptr);
#endif
#if JUCE_PLUGINHOST_AU && (JUCE_MAC || JUCE_IOS)
jassert (dynamic_cast<AudioUnitPluginFormat*> (formats[i]) == nullptr);
#endif
#if JUCE_PLUGINHOST_LADSPA && JUCE_LINUX
jassert (dynamic_cast<LADSPAPluginFormat*> (formats[i]) == nullptr);
#endif
}
#endif
#if JUCE_PLUGINHOST_AU && (JUCE_MAC || JUCE_IOS)
formats.add (new AudioUnitPluginFormat());
#endif
#if JUCE_PLUGINHOST_VST && (JUCE_MAC || JUCE_WINDOWS || JUCE_LINUX || JUCE_IOS)
formats.add (new VSTPluginFormat());
#endif
#if JUCE_PLUGINHOST_VST3 && (JUCE_MAC || JUCE_WINDOWS)
formats.add (new VST3PluginFormat());
#endif
#if JUCE_PLUGINHOST_LADSPA && JUCE_LINUX
formats.add (new LADSPAPluginFormat());
#endif
}
int AudioPluginFormatManager::getNumFormats()
{
return formats.size();
}
AudioPluginFormat* AudioPluginFormatManager::getFormat (const int index)
{
return formats [index];
}
void AudioPluginFormatManager::addFormat (AudioPluginFormat* const format)
{
formats.add (format);
}
AudioPluginInstance* AudioPluginFormatManager::createPluginInstance (const PluginDescription& description, double rate,
int blockSize, String& errorMessage) const
{
if (AudioPluginFormat* format = findFormatForDescription (description, errorMessage))
return format->createInstanceFromDescription (description, rate, blockSize, errorMessage);
return nullptr;
}
void AudioPluginFormatManager::createPluginInstanceAsync (const PluginDescription& description,
double initialSampleRate,
int initialBufferSize,
AudioPluginFormat::InstantiationCompletionCallback* callback)
{
String error;
if (AudioPluginFormat* format = findFormatForDescription (description, error))
return format->createPluginInstanceAsync (description, initialSampleRate, initialBufferSize, callback);
(new PluginFormatManagerHelpers::ErrorCallbackOnMessageThread (error, callback))->post();
}
void AudioPluginFormatManager::createPluginInstanceAsync (const PluginDescription& description,
double initialSampleRate,
int initialBufferSize,
std::function<void (AudioPluginInstance*, const String&)> f)
{
String error;
if (AudioPluginFormat* format = findFormatForDescription (description, error))
return format->createPluginInstanceAsync (description, initialSampleRate, initialBufferSize, f);
(new PluginFormatManagerHelpers::ErrorLambdaOnMessageThread (error, f))->post();
}
AudioPluginFormat* AudioPluginFormatManager::findFormatForDescription (const PluginDescription& description, String& errorMessage) const
{
errorMessage = String();
for (int i = 0; i < formats.size(); ++i)
{
AudioPluginFormat* format;
if ((format = formats.getUnchecked (i))->getName() == description.pluginFormatName
&& format->fileMightContainThisPluginType (description.fileOrIdentifier))
return format;
}
errorMessage = NEEDS_TRANS ("No compatible plug-in format exists for this plug-in");
return nullptr;
}
bool AudioPluginFormatManager::doesPluginStillExist (const PluginDescription& description) const
{
for (int i = 0; i < formats.size(); ++i)
if (formats.getUnchecked(i)->getName() == description.pluginFormatName)
return formats.getUnchecked(i)->doesPluginStillExist (description);
return false;
}
} // namespace juce

+ 0
- 138
source/modules/juce_audio_processors/format/juce_AudioPluginFormatManager.h View File

@@ -1,138 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
This maintains a list of known AudioPluginFormats.
@see AudioPluginFormat
*/
class JUCE_API AudioPluginFormatManager
{
public:
//==============================================================================
AudioPluginFormatManager();
/** Destructor. */
~AudioPluginFormatManager();
//==============================================================================
/** Adds any formats that it knows about, e.g. VST.
*/
void addDefaultFormats();
//==============================================================================
/** Returns the number of types of format that are available.
Use getFormat() to get one of them.
*/
int getNumFormats();
/** Returns one of the available formats.
@see getNumFormats
*/
AudioPluginFormat* getFormat (int index);
//==============================================================================
/** Adds a format to the list.
The object passed in will be owned and deleted by the manager.
*/
void addFormat (AudioPluginFormat* format);
//==============================================================================
/** Tries to load the type for this description, by trying all the formats
that this manager knows about.
The caller is responsible for deleting the object that is returned.
If it can't load the plugin, it returns nullptr and leaves a message in the
errorMessage string.
If you intend to instantiate a AudioUnit v3 plug-in then you must either
use the non-blocking asynchrous version below - or call this method from a
thread other than the message thread and without blocking the message
thread.
*/
AudioPluginInstance* createPluginInstance (const PluginDescription& description,
double initialSampleRate,
int initialBufferSize,
String& errorMessage) const;
/** Tries to asynchronously load the type for this description, by trying
all the formats that this manager knows about.
The caller must supply a callback object which will be called when
the instantantiation has completed.
If it can't load the plugin then the callback function will be called
passing a nullptr as the instance argument along with an error message.
The callback function will be called on the message thread so the caller
must not block the message thread.
The callback object will be deleted automatically after it has been
invoked.
The caller is responsible for deleting the instance that is passed to
the callback function.
If you intend to instantiate a AudioUnit v3 plug-in then you must use
this non-blocking asynchrous version - or call the synchrous method
from an auxiliary thread.
*/
void createPluginInstanceAsync (const PluginDescription& description,
double initialSampleRate,
int initialBufferSize,
AudioPluginFormat::InstantiationCompletionCallback* callback);
void createPluginInstanceAsync (const PluginDescription& description,
double initialSampleRate,
int initialBufferSize,
std::function<void (AudioPluginInstance*, const String&)> completionCallback);
/** Checks that the file or component for this plugin actually still exists.
(This won't try to load the plugin)
*/
bool doesPluginStillExist (const PluginDescription& description) const;
private:
//==============================================================================
//@internal
AudioPluginFormat* findFormatForDescription (const PluginDescription&, String& errorMessage) const;
OwnedArray<AudioPluginFormat> formats;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioPluginFormatManager)
};
} // namespace juce

+ 0
- 535
source/modules/juce_audio_processors/format_types/juce_AU_Shared.h View File

@@ -1,535 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
// This macro can be set if you need to override this internal name for some reason..
#ifndef JUCE_STATE_DICTIONARY_KEY
#define JUCE_STATE_DICTIONARY_KEY "jucePluginState"
#endif
namespace juce
{
struct AudioUnitHelpers
{
class ChannelRemapper
{
public:
ChannelRemapper (AudioProcessor& p) : processor (p), inputLayoutMap (nullptr), outputLayoutMap (nullptr) {}
~ChannelRemapper() {}
void alloc()
{
const int numInputBuses = AudioUnitHelpers::getBusCount (&processor, true);
const int numOutputBuses = AudioUnitHelpers::getBusCount (&processor, false);
initializeChannelMapArray (true, numInputBuses);
initializeChannelMapArray (false, numOutputBuses);
for (int busIdx = 0; busIdx < numInputBuses; ++busIdx)
fillLayoutChannelMaps (true, busIdx);
for (int busIdx = 0; busIdx < numOutputBuses; ++busIdx)
fillLayoutChannelMaps (false, busIdx);
}
void release()
{
inputLayoutMap = outputLayoutMap = nullptr;
inputLayoutMapPtrStorage.free();
outputLayoutMapPtrStorage.free();
inputLayoutMapStorage.free();
outputLayoutMapStorage.free();
}
inline const int* get (bool input, int bus) const noexcept { return (input ? inputLayoutMap : outputLayoutMap) [bus]; }
private:
//==============================================================================
AudioProcessor& processor;
HeapBlock<int*> inputLayoutMapPtrStorage, outputLayoutMapPtrStorage;
HeapBlock<int> inputLayoutMapStorage, outputLayoutMapStorage;
int** inputLayoutMap;
int** outputLayoutMap;
//==============================================================================
void initializeChannelMapArray (bool isInput, const int numBuses)
{
HeapBlock<int*>& layoutMapPtrStorage = isInput ? inputLayoutMapPtrStorage : outputLayoutMapPtrStorage;
HeapBlock<int>& layoutMapStorage = isInput ? inputLayoutMapStorage : outputLayoutMapStorage;
int**& layoutMap = isInput ? inputLayoutMap : outputLayoutMap;
const int totalInChannels = processor.getTotalNumInputChannels();
const int totalOutChannels = processor.getTotalNumOutputChannels();
layoutMapPtrStorage.calloc (static_cast<size_t> (numBuses));
layoutMapStorage.calloc (static_cast<size_t> (isInput ? totalInChannels : totalOutChannels));
layoutMap = layoutMapPtrStorage. get();
int ch = 0;
for (int busIdx = 0; busIdx < numBuses; ++busIdx)
{
layoutMap[busIdx] = layoutMapStorage.get() + ch;
ch += processor.getChannelCountOfBus (isInput, busIdx);
}
}
void fillLayoutChannelMaps (bool isInput, int busNr)
{
int* layoutMap = (isInput ? inputLayoutMap : outputLayoutMap)[busNr];
auto channelFormat = processor.getChannelLayoutOfBus (isInput, busNr);
AudioChannelLayout coreAudioLayout;
zerostruct (coreAudioLayout);
coreAudioLayout.mChannelLayoutTag = CoreAudioLayouts::toCoreAudio (channelFormat);
const int numChannels = channelFormat.size();
auto coreAudioChannels = CoreAudioLayouts::getCoreAudioLayoutChannels (coreAudioLayout);
for (int i = 0; i < numChannels; ++i)
layoutMap[i] = coreAudioChannels.indexOf (channelFormat.getTypeOfChannel (i));
}
};
//==============================================================================
class CoreAudioBufferList
{
public:
CoreAudioBufferList() { reset(); }
//==============================================================================
void prepare (int inChannels, int outChannels, int maxFrames)
{
const int numChannels = jmax (inChannels, outChannels);
scratch.setSize (numChannels, maxFrames);
channels.calloc (static_cast<size_t> (numChannels));
reset();
}
void release()
{
scratch.setSize (0, 0);
channels.free();
}
void reset() noexcept
{
pushIdx = 0;
popIdx = 0;
zeromem (channels.get(), sizeof(float*) * static_cast<size_t> (scratch.getNumChannels()));
}
//==============================================================================
float* setBuffer (const int idx, float* ptr = nullptr) noexcept
{
jassert (idx < scratch.getNumChannels());
return (channels [idx] = uniqueBuffer (idx, ptr));
}
//==============================================================================
float* push() noexcept
{
jassert (pushIdx < scratch.getNumChannels());
return channels [pushIdx++];
}
void push (AudioBufferList& bufferList, const int* channelMap) noexcept
{
jassert (pushIdx < scratch.getNumChannels());
if (bufferList.mNumberBuffers > 0)
{
const UInt32 n = bufferList.mBuffers [0].mDataByteSize /
(bufferList.mBuffers [0].mNumberChannels * sizeof (float));
const bool isInterleaved = isAudioBufferInterleaved (bufferList);
const int numChannels = static_cast<int> (isInterleaved ? bufferList.mBuffers [0].mNumberChannels
: bufferList.mNumberBuffers);
for (int ch = 0; ch < numChannels; ++ch)
{
float* data = push();
int mappedChannel = channelMap [ch];
if (isInterleaved || static_cast<float*> (bufferList.mBuffers [mappedChannel].mData) != data)
copyAudioBuffer (bufferList, mappedChannel, n, data);
}
}
}
//==============================================================================
float* pop() noexcept
{
jassert (popIdx < scratch.getNumChannels());
return channels[popIdx++];
}
void pop (AudioBufferList& buffer, const int* channelMap) noexcept
{
if (buffer.mNumberBuffers > 0)
{
const UInt32 n = buffer.mBuffers [0].mDataByteSize / (buffer.mBuffers [0].mNumberChannels * sizeof (float));
const bool isInterleaved = isAudioBufferInterleaved (buffer);
const int numChannels = static_cast<int> (isInterleaved ? buffer.mBuffers [0].mNumberChannels : buffer.mNumberBuffers);
for (int ch = 0; ch < numChannels; ++ch)
{
int mappedChannel = channelMap [ch];
float* nextBuffer = pop();
if (nextBuffer == buffer.mBuffers [mappedChannel].mData && ! isInterleaved)
continue; // no copying necessary
if (buffer.mBuffers [mappedChannel].mData == nullptr && ! isInterleaved)
buffer.mBuffers [mappedChannel].mData = nextBuffer;
else
copyAudioBuffer (nextBuffer, mappedChannel, n, buffer);
}
}
}
//==============================================================================
AudioSampleBuffer& getBuffer (UInt32 frames) noexcept
{
jassert (pushIdx == scratch.getNumChannels());
#if JUCE_DEBUG
for (int i = 0; i < pushIdx; ++i)
jassert (channels [i] != nullptr);
#endif
mutableBuffer.setDataToReferTo (channels, pushIdx, static_cast<int> (frames));
return mutableBuffer;
}
private:
float* uniqueBuffer (int idx, float* buffer) noexcept
{
if (buffer == nullptr)
return scratch.getWritePointer (idx);
for (int ch = 0; ch < idx; ++ch)
if (buffer == channels[ch])
return scratch.getWritePointer (idx);
return buffer;
}
//==============================================================================
AudioSampleBuffer scratch;
AudioSampleBuffer mutableBuffer;
HeapBlock<float*> channels;
int pushIdx, popIdx;
};
static bool isAudioBufferInterleaved (const AudioBufferList& audioBuffer) noexcept
{
return (audioBuffer.mNumberBuffers == 1 && audioBuffer.mBuffers[0].mNumberChannels > 1);
}
static void clearAudioBuffer (const AudioBufferList& audioBuffer) noexcept
{
for (unsigned int ch = 0; ch < audioBuffer.mNumberBuffers; ++ch)
zeromem (audioBuffer.mBuffers[ch].mData, audioBuffer.mBuffers[ch].mDataByteSize);
}
static void copyAudioBuffer (const AudioBufferList& audioBuffer, const int channel, const UInt32 size, float* dst) noexcept
{
if (! isAudioBufferInterleaved (audioBuffer))
{
jassert (channel < static_cast<int> (audioBuffer.mNumberBuffers));
jassert (audioBuffer.mBuffers[channel].mDataByteSize == (size * sizeof (float)));
memcpy (dst, audioBuffer.mBuffers[channel].mData, size * sizeof (float));
}
else
{
const int numChannels = static_cast<int> (audioBuffer.mBuffers[0].mNumberChannels);
const UInt32 n = static_cast<UInt32> (numChannels) * size;
const float* src = static_cast<const float*> (audioBuffer.mBuffers[0].mData);
jassert (channel < numChannels);
jassert (audioBuffer.mBuffers[0].mDataByteSize == (n * sizeof (float)));
for (const float* inData = src; inData < (src + n); inData += numChannels)
*dst++ = inData[channel];
}
}
static void copyAudioBuffer (const float *src, const int channel, const UInt32 size, AudioBufferList& audioBuffer) noexcept
{
if (! isAudioBufferInterleaved (audioBuffer))
{
jassert (channel < static_cast<int> (audioBuffer.mNumberBuffers));
jassert (audioBuffer.mBuffers[channel].mDataByteSize == (size * sizeof (float)));
memcpy (audioBuffer.mBuffers[channel].mData, src, size * sizeof (float));
}
else
{
const int numChannels = static_cast<int> (audioBuffer.mBuffers[0].mNumberChannels);
const UInt32 n = static_cast<UInt32> (numChannels) * size;
float* dst = static_cast<float*> (audioBuffer.mBuffers[0].mData);
jassert (channel < numChannels);
jassert (audioBuffer.mBuffers[0].mDataByteSize == (n * sizeof (float)));
for (float* outData = dst; outData < (dst + n); outData += numChannels)
outData[channel] = *src++;
}
}
template <int numLayouts>
static bool isLayoutSupported (const AudioProcessor& processor,
bool isInput, int busIdx,
int numChannels,
const short (&channelLayoutList) [numLayouts][2],
bool hasLayoutMap = true)
{
if (const AudioProcessor::Bus* bus = processor.getBus (isInput, busIdx))
{
if (! bus->isNumberOfChannelsSupported (numChannels))
return false;
if (! hasLayoutMap)
return true;
const int numConfigs = sizeof (channelLayoutList) / sizeof (short[2]);
for (int i = 0; i < numConfigs; ++i)
{
if (channelLayoutList[i][isInput ? 0 : 1] == numChannels)
return true;
}
}
return false;
}
static Array<AUChannelInfo> getAUChannelInfo (const AudioProcessor& processor)
{
Array<AUChannelInfo> channelInfo;
auto hasMainInputBus = (AudioUnitHelpers::getBusCount (&processor, true) > 0);
auto hasMainOutputBus = (AudioUnitHelpers::getBusCount (&processor, false) > 0);
if ((! hasMainInputBus) && (! hasMainOutputBus))
{
// midi effect plug-in: no audio
AUChannelInfo info;
info.inChannels = 0;
info.outChannels = 0;
return { &info, 1 };
}
auto layout = processor.getBusesLayout();
auto maxNumChanToCheckFor = 9;
auto defaultInputs = processor.getChannelCountOfBus (true, 0);
auto defaultOutputs = processor.getChannelCountOfBus (false, 0);
SortedSet<int> supportedChannels;
// add the current configuration
if (defaultInputs != 0 || defaultOutputs != 0)
supportedChannels.add ((defaultInputs << 16) | defaultOutputs);
for (auto inChanNum = hasMainInputBus ? 1 : 0; inChanNum <= (hasMainInputBus ? maxNumChanToCheckFor : 0); ++inChanNum)
{
auto inLayout = layout;
if (auto* inBus = processor.getBus (true, 0))
if (! isNumberOfChannelsSupported (inBus, inChanNum, inLayout))
continue;
for (auto outChanNum = hasMainOutputBus ? 1 : 0; outChanNum <= (hasMainOutputBus ? maxNumChanToCheckFor : 0); ++outChanNum)
{
auto outLayout = inLayout;
if (auto* outBus = processor.getBus (false, 0))
if (! isNumberOfChannelsSupported (outBus, outChanNum, outLayout))
continue;
supportedChannels.add (((hasMainInputBus ? outLayout.getMainInputChannels() : 0) << 16)
| (hasMainOutputBus ? outLayout.getMainOutputChannels() : 0));
}
}
auto hasInOutMismatch = false;
for (auto supported : supportedChannels)
{
auto numInputs = (supported >> 16) & 0xffff;
auto numOutputs = (supported >> 0) & 0xffff;
if (numInputs != numOutputs)
{
hasInOutMismatch = true;
break;
}
}
auto hasUnsupportedInput = ! hasMainInputBus, hasUnsupportedOutput = ! hasMainOutputBus;
for (auto inChanNum = hasMainInputBus ? 1 : 0; inChanNum <= (hasMainInputBus ? maxNumChanToCheckFor : 0); ++inChanNum)
{
auto channelConfiguration = (inChanNum << 16) | (hasInOutMismatch ? defaultOutputs : inChanNum);
if (! supportedChannels.contains (channelConfiguration))
{
hasUnsupportedInput = true;
break;
}
}
for (auto outChanNum = hasMainOutputBus ? 1 : 0; outChanNum <= (hasMainOutputBus ? maxNumChanToCheckFor : 0); ++outChanNum)
{
auto channelConfiguration = ((hasInOutMismatch ? defaultInputs : outChanNum) << 16) | outChanNum;
if (! supportedChannels.contains (channelConfiguration))
{
hasUnsupportedOutput = true;
break;
}
}
for (auto supported : supportedChannels)
{
auto numInputs = (supported >> 16) & 0xffff;
auto numOutputs = (supported >> 0) & 0xffff;
AUChannelInfo info;
// see here: https://developer.apple.com/library/mac/documentation/MusicAudio/Conceptual/AudioUnitProgrammingGuide/TheAudioUnit/TheAudioUnit.html
info.inChannels = static_cast<SInt16> (hasMainInputBus ? (hasUnsupportedInput ? numInputs : (hasInOutMismatch && (! hasUnsupportedOutput) ? -2 : -1)) : 0);
info.outChannels = static_cast<SInt16> (hasMainOutputBus ? (hasUnsupportedOutput ? numOutputs : (hasInOutMismatch && (! hasUnsupportedInput) ? -2 : -1)) : 0);
if (info.inChannels == -2 && info.outChannels == -2)
info.inChannels = -1;
int j;
for (j = 0; j < channelInfo.size(); ++j)
if (info.inChannels == channelInfo.getReference (j).inChannels
&& info.outChannels == channelInfo.getReference (j).outChannels)
break;
if (j >= channelInfo.size())
channelInfo.add (info);
}
return channelInfo;
}
static bool isNumberOfChannelsSupported (const AudioProcessor::Bus* b, int numChannels, AudioProcessor::BusesLayout& inOutCurrentLayout)
{
auto potentialSets = AudioChannelSet::channelSetsWithNumberOfChannels (static_cast<int> (numChannels));
for (auto set : potentialSets)
{
auto copy = inOutCurrentLayout;
if (b->isLayoutSupported (set, &copy))
{
inOutCurrentLayout = copy;
return true;
}
}
return false;
}
//==============================================================================
static int getBusCount (const AudioProcessor* juceFilter, bool isInput)
{
int busCount = juceFilter->getBusCount (isInput);
#ifdef JucePlugin_PreferredChannelConfigurations
short configs[][2] = {JucePlugin_PreferredChannelConfigurations};
const int numConfigs = sizeof (configs) / sizeof (short[2]);
bool hasOnlyZeroChannels = true;
for (int i = 0; i < numConfigs && hasOnlyZeroChannels == true; ++i)
if (configs[i][isInput ? 0 : 1] != 0)
hasOnlyZeroChannels = false;
busCount = jmin (busCount, hasOnlyZeroChannels ? 0 : 1);
#endif
return busCount;
}
static bool setBusesLayout (AudioProcessor* juceFilter, const AudioProcessor::BusesLayout& requestedLayouts)
{
#ifdef JucePlugin_PreferredChannelConfigurations
AudioProcessor::BusesLayout copy (requestedLayouts);
for (int dir = 0; dir < 2; ++dir)
{
const bool isInput = (dir == 0);
const int actualBuses = juceFilter->getBusCount (isInput);
const int auNumBuses = getBusCount (juceFilter, isInput);
Array<AudioChannelSet>& buses = (isInput ? copy.inputBuses : copy.outputBuses);
for (int i = auNumBuses; i < actualBuses; ++i)
buses.add (AudioChannelSet::disabled());
}
return juceFilter->setBusesLayout (copy);
#else
return juceFilter->setBusesLayout (requestedLayouts);
#endif
}
static AudioProcessor::BusesLayout getBusesLayout (const AudioProcessor* juceFilter)
{
#ifdef JucePlugin_PreferredChannelConfigurations
AudioProcessor::BusesLayout layout = juceFilter->getBusesLayout();
for (int dir = 0; dir < 2; ++dir)
{
const bool isInput = (dir == 0);
const int actualBuses = juceFilter->getBusCount (isInput);
const int auNumBuses = getBusCount (juceFilter, isInput);
auto& buses = (isInput ? layout.inputBuses : layout.outputBuses);
for (int i = auNumBuses; i < actualBuses; ++i)
buses.removeLast();
}
return layout;
#else
return juceFilter->getBusesLayout();
#endif
}
};
} // namespace juce

+ 0
- 79
source/modules/juce_audio_processors/format_types/juce_AudioUnitPluginFormat.h View File

@@ -1,79 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
#if (JUCE_PLUGINHOST_AU && (JUCE_MAC || JUCE_IOS)) || DOXYGEN
//==============================================================================
/**
Implements a plugin format manager for AudioUnits.
*/
class JUCE_API AudioUnitPluginFormat : public AudioPluginFormat
{
public:
//==============================================================================
AudioUnitPluginFormat();
~AudioUnitPluginFormat();
//==============================================================================
String getName() const override { return "AudioUnit"; }
void findAllTypesForFile (OwnedArray<PluginDescription>&, const String& fileOrIdentifier) override;
bool fileMightContainThisPluginType (const String& fileOrIdentifier) override;
String getNameOfPluginFromIdentifier (const String& fileOrIdentifier) override;
bool pluginNeedsRescanning (const PluginDescription&) override;
StringArray searchPathsForPlugins (const FileSearchPath&, bool recursive, bool) override;
bool doesPluginStillExist (const PluginDescription&) override;
FileSearchPath getDefaultLocationsToSearch() override;
bool canScanForPlugins() const override { return true; }
private:
//==============================================================================
void createPluginInstance (const PluginDescription&,
double initialSampleRate,
int initialBufferSize,
void* userData,
void (*callback) (void*, AudioPluginInstance*, const String&)) override;
bool requiresUnblockedMessageThreadDuringCreation (const PluginDescription&) const noexcept override;
//==============================================================================
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioUnitPluginFormat)
};
#endif
//==============================================================================
#if MAC_OS_X_VERSION_MAX_ALLOWED < 101200
enum
{
/** Custom AudioUnit property used to indicate MPE support */
kAudioUnitProperty_SupportsMPE = 58
};
#endif
}

+ 0
- 2463
source/modules/juce_audio_processors/format_types/juce_AudioUnitPluginFormat.mm
File diff suppressed because it is too large
View File


+ 0
- 718
source/modules/juce_audio_processors/format_types/juce_LADSPAPluginFormat.cpp View File

@@ -1,718 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
#if JUCE_PLUGINHOST_LADSPA && JUCE_LINUX
#include "ladspa.h"
namespace juce
{
static int shellLADSPAUIDToCreate = 0;
static int insideLADSPACallback = 0;
#define JUCE_LADSPA_LOGGING 1
#if JUCE_LADSPA_LOGGING
#define JUCE_LADSPA_LOG(x) Logger::writeToLog (x);
#else
#define JUCE_LADSPA_LOG(x)
#endif
//==============================================================================
class LADSPAModuleHandle : public ReferenceCountedObject
{
public:
LADSPAModuleHandle (const File& f)
: file (f), moduleMain (nullptr)
{
getActiveModules().add (this);
}
~LADSPAModuleHandle()
{
getActiveModules().removeFirstMatchingValue (this);
close();
}
typedef ReferenceCountedObjectPtr<LADSPAModuleHandle> Ptr;
static Array <LADSPAModuleHandle*>& getActiveModules()
{
static Array <LADSPAModuleHandle*> activeModules;
return activeModules;
}
static LADSPAModuleHandle* findOrCreateModule (const File& file)
{
for (int i = getActiveModules().size(); --i >= 0;)
{
LADSPAModuleHandle* const module = getActiveModules().getUnchecked(i);
if (module->file == file)
return module;
}
++insideLADSPACallback;
shellLADSPAUIDToCreate = 0;
JUCE_LADSPA_LOG ("Loading LADSPA module: " + file.getFullPathName());
ScopedPointer<LADSPAModuleHandle> m (new LADSPAModuleHandle (file));
if (! m->open())
m = nullptr;
--insideLADSPACallback;
return m.release();
}
File file;
LADSPA_Descriptor_Function moduleMain;
private:
DynamicLibrary module;
bool open()
{
module.open (file.getFullPathName());
moduleMain = (LADSPA_Descriptor_Function) module.getFunction ("ladspa_descriptor");
return moduleMain != nullptr;
}
void close()
{
module.close();
}
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LADSPAModuleHandle)
};
//==============================================================================
class LADSPAPluginInstance : public AudioPluginInstance
{
public:
LADSPAPluginInstance (const LADSPAModuleHandle::Ptr& m)
: module (m), plugin (nullptr), handle (nullptr),
initialised (false), tempBuffer (1, 1)
{
++insideLADSPACallback;
name = module->file.getFileNameWithoutExtension();
JUCE_LADSPA_LOG ("Creating LADSPA instance: " + name);
if (module->moduleMain != nullptr)
{
plugin = module->moduleMain (shellLADSPAUIDToCreate);
if (plugin == nullptr)
{
JUCE_LADSPA_LOG ("Cannot find any valid descriptor in shared library");
--insideLADSPACallback;
return;
}
}
else
{
JUCE_LADSPA_LOG ("Cannot find any valid plugin in shared library");
--insideLADSPACallback;
return;
}
const double sampleRate = getSampleRate() > 0 ? getSampleRate() : 44100.0;
handle = plugin->instantiate (plugin, (uint32) sampleRate);
--insideLADSPACallback;
}
~LADSPAPluginInstance()
{
const ScopedLock sl (lock);
jassert (insideLADSPACallback == 0);
if (handle != nullptr && plugin != nullptr && plugin->cleanup != nullptr)
plugin->cleanup (handle);
initialised = false;
module = nullptr;
plugin = nullptr;
handle = nullptr;
}
void initialise (double initialSampleRate, int initialBlockSize)
{
setPlayConfigDetails (inputs.size(), outputs.size(), initialSampleRate, initialBlockSize);
if (initialised || plugin == nullptr || handle == nullptr)
return;
JUCE_LADSPA_LOG ("Initialising LADSPA: " + name);
initialised = true;
inputs.clear();
outputs.clear();
parameters.clear();
for (unsigned int i = 0; i < plugin->PortCount; ++i)
{
const LADSPA_PortDescriptor portDesc = plugin->PortDescriptors[i];
if ((portDesc & LADSPA_PORT_CONTROL) != 0)
parameters.add (i);
if ((portDesc & LADSPA_PORT_AUDIO) != 0)
{
if ((portDesc & LADSPA_PORT_INPUT) != 0) inputs.add (i);
if ((portDesc & LADSPA_PORT_OUTPUT) != 0) outputs.add (i);
}
}
parameterValues.calloc (parameters.size());
for (int i = 0; i < parameters.size(); ++i)
plugin->connect_port (handle, parameters[i], &(parameterValues[i].scaled));
setPlayConfigDetails (inputs.size(), outputs.size(), initialSampleRate, initialBlockSize);
setCurrentProgram (0);
setLatencySamples (0);
// Some plugins crash if this doesn't happen:
if (plugin->activate != nullptr) plugin->activate (handle);
if (plugin->deactivate != nullptr) plugin->deactivate (handle);
}
//==============================================================================
// AudioPluginInstance methods:
void fillInPluginDescription (PluginDescription& desc) const
{
desc.name = getName();
desc.fileOrIdentifier = module->file.getFullPathName();
desc.uid = getUID();
desc.lastFileModTime = module->file.getLastModificationTime();
desc.lastInfoUpdateTime = Time::getCurrentTime();
desc.pluginFormatName = "LADSPA";
desc.category = getCategory();
desc.manufacturerName = plugin != nullptr ? String (plugin->Maker) : String();
desc.version = getVersion();
desc.numInputChannels = getTotalNumInputChannels();
desc.numOutputChannels = getTotalNumOutputChannels();
desc.isInstrument = false;
}
const String getName() const
{
if (plugin != nullptr && plugin->Label != nullptr)
return plugin->Label;
return name;
}
int getUID() const
{
if (plugin != nullptr && plugin->UniqueID != 0)
return (int) plugin->UniqueID;
return module->file.hashCode();
}
String getVersion() const { return LADSPA_VERSION; }
String getCategory() const { return "Effect"; }
bool acceptsMidi() const { return false; }
bool producesMidi() const { return false; }
double getTailLengthSeconds() const { return 0.0; }
//==============================================================================
void prepareToPlay (double newSampleRate, int samplesPerBlockExpected)
{
setLatencySamples (0);
initialise (newSampleRate, samplesPerBlockExpected);
if (initialised)
{
tempBuffer.setSize (jmax (1, outputs.size()), samplesPerBlockExpected);
// dodgy hack to force some plugins to initialise the sample rate..
if (getNumParameters() > 0)
{
const float old = getParameter (0);
setParameter (0, (old < 0.5f) ? 1.0f : 0.0f);
setParameter (0, old);
}
if (plugin->activate != nullptr)
plugin->activate (handle);
}
}
void releaseResources()
{
if (handle != nullptr && plugin->deactivate != nullptr)
plugin->deactivate (handle);
tempBuffer.setSize (1, 1);
}
void processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages)
{
const int numSamples = buffer.getNumSamples();
if (initialised && plugin != nullptr && handle != nullptr)
{
for (int i = 0; i < inputs.size(); ++i)
plugin->connect_port (handle, inputs[i],
i < buffer.getNumChannels() ? buffer.getWritePointer (i) : nullptr);
if (plugin->run != nullptr)
{
for (int i = 0; i < outputs.size(); ++i)
plugin->connect_port (handle, outputs.getUnchecked(i),
i < buffer.getNumChannels() ? buffer.getWritePointer (i) : nullptr);
plugin->run (handle, numSamples);
return;
}
if (plugin->run_adding != nullptr)
{
tempBuffer.setSize (outputs.size(), numSamples);
tempBuffer.clear();
for (int i = 0; i < outputs.size(); ++i)
plugin->connect_port (handle, outputs.getUnchecked(i), tempBuffer.getWritePointer (i));
plugin->run_adding (handle, numSamples);
for (int i = 0; i < outputs.size(); ++i)
if (i < buffer.getNumChannels())
buffer.copyFrom (i, 0, tempBuffer, i, 0, numSamples);
return;
}
jassertfalse; // no callback to use?
}
for (int i = getTotalNumInputChannels(), e = getTotalNumOutputChannels(); i < e; ++i)
buffer.clear (i, 0, numSamples);
}
bool isInputChannelStereoPair (int index) const { return isPositiveAndBelow (index, getTotalNumInputChannels()); }
bool isOutputChannelStereoPair (int index) const { return isPositiveAndBelow (index, getTotalNumOutputChannels()); }
const String getInputChannelName (const int index) const
{
if (isPositiveAndBelow (index, getTotalNumInputChannels()))
return String (plugin->PortNames [inputs [index]]).trim();
return {};
}
const String getOutputChannelName (const int index) const
{
if (isPositiveAndBelow (index, getTotalNumInputChannels()))
return String (plugin->PortNames [outputs [index]]).trim();
return {};
}
//==============================================================================
int getNumParameters() { return handle != nullptr ? parameters.size() : 0; }
bool isParameterAutomatable (int index) const
{
return plugin != nullptr
&& (plugin->PortDescriptors [parameters[index]] & LADSPA_PORT_INPUT) != 0;
}
float getParameter (int index)
{
if (plugin != nullptr && isPositiveAndBelow (index, parameters.size()))
{
const ScopedLock sl (lock);
return parameterValues[index].unscaled;
}
return 0.0f;
}
void setParameter (int index, float newValue)
{
if (plugin != nullptr && isPositiveAndBelow (index, parameters.size()))
{
const ScopedLock sl (lock);
ParameterValue& p = parameterValues[index];
if (p.unscaled != newValue)
p = ParameterValue (getNewParamScaled (plugin->PortRangeHints [parameters[index]], newValue), newValue);
}
}
const String getParameterName (int index)
{
if (plugin != nullptr)
{
jassert (isPositiveAndBelow (index, parameters.size()));
return String (plugin->PortNames [parameters [index]]).trim();
}
return {};
}
const String getParameterText (int index)
{
if (plugin != nullptr)
{
jassert (index >= 0 && index < parameters.size());
const LADSPA_PortRangeHint& hint = plugin->PortRangeHints [parameters [index]];
if (LADSPA_IS_HINT_INTEGER (hint.HintDescriptor))
return String ((int) parameterValues[index].scaled);
return String (parameterValues[index].scaled, 4);
}
return {};
}
//==============================================================================
int getNumPrograms() { return 0; }
int getCurrentProgram() { return 0; }
void setCurrentProgram (int newIndex)
{
if (plugin != nullptr)
for (int i = 0; i < parameters.size(); ++i)
parameterValues[i] = getParamValue (plugin->PortRangeHints [parameters[i]]);
}
const String getProgramName (int index)
{
// XXX
return {};
}
void changeProgramName (int index, const String& newName)
{
// XXX
}
//==============================================================================
void getStateInformation (MemoryBlock& destData)
{
destData.setSize (sizeof (float) * getNumParameters());
destData.fillWith (0);
float* const p = (float*) ((char*) destData.getData());
for (int i = 0; i < getNumParameters(); ++i)
p[i] = getParameter(i);
}
void getCurrentProgramStateInformation (MemoryBlock& destData)
{
getStateInformation (destData);
}
void setStateInformation (const void* data, int sizeInBytes)
{
const float* p = static_cast<const float*> (data);
for (int i = 0; i < getNumParameters(); ++i)
setParameter (i, p[i]);
}
void setCurrentProgramStateInformation (const void* data, int sizeInBytes)
{
setStateInformation (data, sizeInBytes);
}
bool hasEditor() const
{
return false;
}
AudioProcessorEditor* createEditor()
{
return nullptr;
}
bool isValid() const
{
return handle != nullptr;
}
LADSPAModuleHandle::Ptr module;
const LADSPA_Descriptor* plugin;
private:
LADSPA_Handle handle;
String name;
CriticalSection lock;
bool initialised;
AudioSampleBuffer tempBuffer;
Array<int> inputs, outputs, parameters;
struct ParameterValue
{
inline ParameterValue() noexcept : scaled (0), unscaled (0) {}
inline ParameterValue (float s, float u) noexcept : scaled (s), unscaled (u) {}
float scaled, unscaled;
};
HeapBlock<ParameterValue> parameterValues;
//==============================================================================
static float scaledValue (float low, float high, float alpha, bool useLog) noexcept
{
if (useLog && low > 0 && high > 0)
return expf (logf (low) * (1.0f - alpha) + logf (high) * alpha);
return low + (high - low) * alpha;
}
static float toIntIfNecessary (const LADSPA_PortRangeHintDescriptor& desc, float value)
{
return LADSPA_IS_HINT_INTEGER (desc) ? ((float) (int) value) : value;
}
float getNewParamScaled (const LADSPA_PortRangeHint& hint, float newValue) const
{
const LADSPA_PortRangeHintDescriptor& desc = hint.HintDescriptor;
if (LADSPA_IS_HINT_TOGGLED (desc))
return (newValue < 0.5f) ? 0.0f : 1.0f;
const float scale = LADSPA_IS_HINT_SAMPLE_RATE (desc) ? (float) getSampleRate() : 1.0f;
const float lower = hint.LowerBound * scale;
const float upper = hint.UpperBound * scale;
if (LADSPA_IS_HINT_BOUNDED_BELOW (desc) && LADSPA_IS_HINT_BOUNDED_ABOVE (desc))
return toIntIfNecessary (desc, scaledValue (lower, upper, newValue, LADSPA_IS_HINT_LOGARITHMIC (desc)));
if (LADSPA_IS_HINT_BOUNDED_BELOW (desc)) return toIntIfNecessary (desc, newValue);
if (LADSPA_IS_HINT_BOUNDED_ABOVE (desc)) return toIntIfNecessary (desc, newValue * upper);
return 0.0f;
}
ParameterValue getParamValue (const LADSPA_PortRangeHint& hint) const
{
const LADSPA_PortRangeHintDescriptor& desc = hint.HintDescriptor;
if (LADSPA_IS_HINT_HAS_DEFAULT (desc))
{
if (LADSPA_IS_HINT_DEFAULT_0 (desc)) return ParameterValue();
if (LADSPA_IS_HINT_DEFAULT_1 (desc)) return ParameterValue (1.0f, 1.0f);
if (LADSPA_IS_HINT_DEFAULT_100 (desc)) return ParameterValue (100.0f, 0.5f);
if (LADSPA_IS_HINT_DEFAULT_440 (desc)) return ParameterValue (440.0f, 0.5f);
const float scale = LADSPA_IS_HINT_SAMPLE_RATE (desc) ? (float) getSampleRate() : 1.0f;
const float lower = hint.LowerBound * scale;
const float upper = hint.UpperBound * scale;
if (LADSPA_IS_HINT_BOUNDED_BELOW (desc) && LADSPA_IS_HINT_DEFAULT_MINIMUM (desc)) return ParameterValue (lower, 0.0f);
if (LADSPA_IS_HINT_BOUNDED_ABOVE (desc) && LADSPA_IS_HINT_DEFAULT_MAXIMUM (desc)) return ParameterValue (upper, 1.0f);
if (LADSPA_IS_HINT_BOUNDED_BELOW (desc))
{
const bool useLog = LADSPA_IS_HINT_LOGARITHMIC (desc);
if (LADSPA_IS_HINT_DEFAULT_LOW (desc)) return ParameterValue (scaledValue (lower, upper, 0.25f, useLog), 0.25f);
if (LADSPA_IS_HINT_DEFAULT_MIDDLE (desc)) return ParameterValue (scaledValue (lower, upper, 0.50f, useLog), 0.50f);
if (LADSPA_IS_HINT_DEFAULT_HIGH (desc)) return ParameterValue (scaledValue (lower, upper, 0.75f, useLog), 0.75f);
}
}
return ParameterValue();
}
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LADSPAPluginInstance)
};
//==============================================================================
//==============================================================================
LADSPAPluginFormat::LADSPAPluginFormat() {}
LADSPAPluginFormat::~LADSPAPluginFormat() {}
void LADSPAPluginFormat::findAllTypesForFile (OwnedArray <PluginDescription>& results,
const String& fileOrIdentifier)
{
if (! fileMightContainThisPluginType (fileOrIdentifier))
return;
PluginDescription desc;
desc.fileOrIdentifier = fileOrIdentifier;
desc.uid = 0;
ScopedPointer<LADSPAPluginInstance> instance (dynamic_cast<LADSPAPluginInstance*> (createInstanceFromDescription (desc, 44100.0, 512)));
if (instance == nullptr || ! instance->isValid())
return;
instance->initialise (44100.0, 512);
instance->fillInPluginDescription (desc);
if (instance->module->moduleMain != nullptr)
{
for (int uid = 0;; ++uid)
{
if (const LADSPA_Descriptor* plugin = instance->module->moduleMain (uid))
{
desc.uid = uid;
desc.name = plugin->Name != nullptr ? plugin->Name : "Unknown";
if (! arrayContainsPlugin (results, desc))
results.add (new PluginDescription (desc));
}
else
{
break;
}
}
}
}
void LADSPAPluginFormat::createPluginInstance (const PluginDescription& desc,
double sampleRate, int blockSize,
void* userData,
void (*callback) (void*, AudioPluginInstance*, const String&))
{
ScopedPointer<LADSPAPluginInstance> result;
if (fileMightContainThisPluginType (desc.fileOrIdentifier))
{
File file (desc.fileOrIdentifier);
const File previousWorkingDirectory (File::getCurrentWorkingDirectory());
file.getParentDirectory().setAsCurrentWorkingDirectory();
const LADSPAModuleHandle::Ptr module (LADSPAModuleHandle::findOrCreateModule (file));
if (module != nullptr)
{
shellLADSPAUIDToCreate = desc.uid;
result = new LADSPAPluginInstance (module);
if (result->plugin != nullptr && result->isValid())
result->initialise (sampleRate, blockSize);
else
result = nullptr;
}
previousWorkingDirectory.setAsCurrentWorkingDirectory();
}
String errorMsg;
if (result == nullptr)
errorMsg = String (NEEDS_TRANS ("Unable to load XXX plug-in file")).replace ("XXX", "LADSPA");
callback (userData, result.release(), errorMsg);
}
bool LADSPAPluginFormat::requiresUnblockedMessageThreadDuringCreation (const PluginDescription&) const noexcept
{
return false;
}
bool LADSPAPluginFormat::fileMightContainThisPluginType (const String& fileOrIdentifier)
{
const File f (File::createFileWithoutCheckingPath (fileOrIdentifier));
return f.existsAsFile() && f.hasFileExtension (".so");
}
String LADSPAPluginFormat::getNameOfPluginFromIdentifier (const String& fileOrIdentifier)
{
return fileOrIdentifier;
}
bool LADSPAPluginFormat::pluginNeedsRescanning (const PluginDescription& desc)
{
return File (desc.fileOrIdentifier).getLastModificationTime() != desc.lastFileModTime;
}
bool LADSPAPluginFormat::doesPluginStillExist (const PluginDescription& desc)
{
return File::createFileWithoutCheckingPath (desc.fileOrIdentifier).exists();
}
StringArray LADSPAPluginFormat::searchPathsForPlugins (const FileSearchPath& directoriesToSearch, const bool recursive, bool)
{
StringArray results;
for (int j = 0; j < directoriesToSearch.getNumPaths(); ++j)
recursiveFileSearch (results, directoriesToSearch[j], recursive);
return results;
}
void LADSPAPluginFormat::recursiveFileSearch (StringArray& results, const File& dir, const bool recursive)
{
DirectoryIterator iter (dir, false, "*", File::findFilesAndDirectories);
while (iter.next())
{
const File f (iter.getFile());
bool isPlugin = false;
if (fileMightContainThisPluginType (f.getFullPathName()))
{
isPlugin = true;
results.add (f.getFullPathName());
}
if (recursive && (! isPlugin) && f.isDirectory())
recursiveFileSearch (results, f, true);
}
}
FileSearchPath LADSPAPluginFormat::getDefaultLocationsToSearch()
{
return FileSearchPath (SystemStats::getEnvironmentVariable ("LADSPA_PATH",
"/usr/lib/ladspa;/usr/local/lib/ladspa;~/.ladspa")
.replace (":", ";"));
}
} // namespace juce
#endif

+ 0
- 70
source/modules/juce_audio_processors/format_types/juce_LADSPAPluginFormat.h View File

@@ -1,70 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
#if (JUCE_PLUGINHOST_LADSPA && JUCE_LINUX) || DOXYGEN
//==============================================================================
/**
Implements a plugin format manager for LADSPA plugins.
*/
class JUCE_API LADSPAPluginFormat : public AudioPluginFormat
{
public:
LADSPAPluginFormat();
~LADSPAPluginFormat();
//==============================================================================
String getName() const override { return "LADSPA"; }
void findAllTypesForFile (OwnedArray<PluginDescription>&, const String& fileOrIdentifier) override;
bool fileMightContainThisPluginType (const String& fileOrIdentifier) override;
String getNameOfPluginFromIdentifier (const String& fileOrIdentifier) override;
bool pluginNeedsRescanning (const PluginDescription&) override;
StringArray searchPathsForPlugins (const FileSearchPath&, bool recursive, bool) override;
bool doesPluginStillExist (const PluginDescription&) override;
FileSearchPath getDefaultLocationsToSearch() override;
bool canScanForPlugins() const override { return true; }
private:
//==============================================================================
void createPluginInstance (const PluginDescription&, double initialSampleRate,
int initialBufferSize, void* userData,
void (*callback) (void*, AudioPluginInstance*, const String&)) override;
bool requiresUnblockedMessageThreadDuringCreation (const PluginDescription&) const noexcept override;
private:
void recursiveFileSearch (StringArray&, const File&, bool recursive);
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LADSPAPluginFormat)
};
#endif
}

+ 0
- 633
source/modules/juce_audio_processors/format_types/juce_VST3Common.h View File

@@ -1,633 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
#define JUCE_DECLARE_VST3_COM_REF_METHODS \
Steinberg::uint32 PLUGIN_API addRef() override { return (Steinberg::uint32) ++refCount; } \
Steinberg::uint32 PLUGIN_API release() override { const int r = --refCount; if (r == 0) delete this; return (Steinberg::uint32) r; }
#define JUCE_DECLARE_VST3_COM_QUERY_METHODS \
Steinberg::tresult PLUGIN_API queryInterface (const Steinberg::TUID, void** obj) override \
{ \
jassertfalse; \
*obj = nullptr; \
return Steinberg::kNotImplemented; \
}
static bool doUIDsMatch (const Steinberg::TUID a, const Steinberg::TUID b) noexcept
{
return std::memcmp (a, b, sizeof (Steinberg::TUID)) == 0;
}
#define TEST_FOR_AND_RETURN_IF_VALID(iidToTest, ClassType) \
if (doUIDsMatch (iidToTest, ClassType::iid)) \
{ \
addRef(); \
*obj = dynamic_cast<ClassType*> (this); \
return Steinberg::kResultOk; \
}
#define TEST_FOR_COMMON_BASE_AND_RETURN_IF_VALID(iidToTest, CommonClassType, SourceClassType) \
if (doUIDsMatch (iidToTest, CommonClassType::iid)) \
{ \
addRef(); \
*obj = (CommonClassType*) static_cast<SourceClassType*> (this); \
return Steinberg::kResultOk; \
}
//==============================================================================
inline juce::String toString (const Steinberg::char8* string) noexcept { return juce::String (string); }
inline juce::String toString (const Steinberg::char16* string) noexcept { return juce::String (juce::CharPointer_UTF16 ((juce::CharPointer_UTF16::CharType*) string)); }
// NB: The casts are handled by a Steinberg::UString operator
inline juce::String toString (const Steinberg::UString128& string) noexcept { return toString (static_cast<const Steinberg::char16*> (string)); }
inline juce::String toString (const Steinberg::UString256& string) noexcept { return toString (static_cast<const Steinberg::char16*> (string)); }
inline void toString128 (Steinberg::Vst::String128 result, const char* source)
{
Steinberg::UString (result, 128).fromAscii (source);
}
inline void toString128 (Steinberg::Vst::String128 result, const juce::String& source)
{
Steinberg::UString (result, 128).fromAscii (source.toUTF8());
}
inline Steinberg::Vst::TChar* toString (const juce::String& source) noexcept
{
return reinterpret_cast<Steinberg::Vst::TChar*> (source.toUTF16().getAddress());
}
#if JUCE_WINDOWS
static const Steinberg::FIDString defaultVST3WindowType = Steinberg::kPlatformTypeHWND;
#else
static const Steinberg::FIDString defaultVST3WindowType = Steinberg::kPlatformTypeNSView;
#endif
//==============================================================================
static inline Steinberg::Vst::SpeakerArrangement getArrangementForBus (Steinberg::Vst::IAudioProcessor* processor,
bool isInput, int busIndex)
{
Steinberg::Vst::SpeakerArrangement arrangement = Steinberg::Vst::SpeakerArr::kEmpty;
if (processor != nullptr)
processor->getBusArrangement (isInput ? Steinberg::Vst::kInput : Steinberg::Vst::kOutput,
(Steinberg::int32) busIndex, arrangement);
return arrangement;
}
/** For the sake of simplicity, there can only be 1 arrangement type per channel count.
i.e.: 4 channels == k31Cine OR k40Cine
*/
static inline Steinberg::Vst::SpeakerArrangement getArrangementForNumChannels (int numChannels) noexcept
{
using namespace Steinberg::Vst::SpeakerArr;
switch (numChannels)
{
case 0: return kEmpty;
case 1: return kMono;
case 2: return kStereo;
case 3: return k30Cine;
case 4: return k31Cine;
case 5: return k50;
case 6: return k51;
case 7: return k61Cine;
case 8: return k71CineFullFront;
case 9: return k90;
case 10: return k91;
case 11: return k101;
case 12: return k111;
case 13: return k130;
case 14: return k131;
case 24: return (Steinberg::Vst::SpeakerArrangement) 1929904127; // k222
default: break;
}
jassert (numChannels >= 0);
juce::BigInteger bi;
bi.setRange (0, jmin (numChannels, (int) (sizeof (Steinberg::Vst::SpeakerArrangement) * 8)), true);
return (Steinberg::Vst::SpeakerArrangement) bi.toInt64();
}
static inline Steinberg::Vst::Speaker getSpeakerType (const AudioChannelSet& set, AudioChannelSet::ChannelType type) noexcept
{
using namespace Steinberg::Vst;
switch (type)
{
case AudioChannelSet::left: return kSpeakerL;
case AudioChannelSet::right: return kSpeakerR;
case AudioChannelSet::centre: return (set == AudioChannelSet::mono() ? kSpeakerM : kSpeakerC);
case AudioChannelSet::LFE: return kSpeakerLfe;
case AudioChannelSet::leftSurround: return kSpeakerLs;
case AudioChannelSet::rightSurround: return kSpeakerRs;
case AudioChannelSet::leftCentre: return kSpeakerLc;
case AudioChannelSet::rightCentre: return kSpeakerRc;
case AudioChannelSet::centreSurround: return kSpeakerCs;
case AudioChannelSet::leftSurroundSide: return (1 << 26); /* kSpeakerLcs */
case AudioChannelSet::rightSurroundSide: return (1 << 27); /* kSpeakerRcs */
case AudioChannelSet::topMiddle: return (1 << 11); /* kSpeakerTm */
case AudioChannelSet::topFrontLeft: return kSpeakerTfl;
case AudioChannelSet::topFrontCentre: return kSpeakerTfc;
case AudioChannelSet::topFrontRight: return kSpeakerTfr;
case AudioChannelSet::topRearLeft: return kSpeakerTrl;
case AudioChannelSet::topRearCentre: return kSpeakerTrc;
case AudioChannelSet::topRearRight: return kSpeakerTrr;
case AudioChannelSet::LFE2: return kSpeakerLfe2;
case AudioChannelSet::leftSurroundRear: return kSpeakerSl;
case AudioChannelSet::rightSurroundRear: return kSpeakerSr;
case AudioChannelSet::wideLeft: return kSpeakerPl;
case AudioChannelSet::wideRight: return kSpeakerPr;
case AudioChannelSet::ambisonicW: return (1 << 20); /* kSpeakerW */
case AudioChannelSet::ambisonicX: return (1 << 21); /* kSpeakerX */
case AudioChannelSet::ambisonicY: return (1 << 22); /* kSpeakerY */
case AudioChannelSet::ambisonicZ: return (1 << 23); /* kSpeakerZ */
case AudioChannelSet::topSideLeft: return (1 << 24); /* kSpeakerTsl */
case AudioChannelSet::topSideRight: return (1 << 25); /* kSpeakerTsr */
case AudioChannelSet::discreteChannel0: return kSpeakerM;
default:
break;
}
switch (static_cast<int> (type))
{
case (int) AudioChannelSet::discreteChannel0 + 3: return (1 << 28); /* kSpeakerBfl */
case (int) AudioChannelSet::discreteChannel0 + 4: return (1 << 29); /* kSpeakerBfc */
case (int) AudioChannelSet::discreteChannel0 + 5: return (1 << 30); /* kSpeakerBfr */
default:
break;
}
auto channelIndex = static_cast<Steinberg::Vst::Speaker> (type) - (static_cast<Steinberg::Vst::Speaker> (AudioChannelSet::discreteChannel0) + 6ull);
return (1ull << (channelIndex + 33ull /* last speaker in vst layout + 1 */));
}
static inline AudioChannelSet::ChannelType getChannelType (Steinberg::Vst::SpeakerArrangement arr, Steinberg::Vst::Speaker type) noexcept
{
using namespace Steinberg::Vst;
switch (type)
{
case kSpeakerL: return AudioChannelSet::left;
case kSpeakerR: return AudioChannelSet::right;
case kSpeakerC: return AudioChannelSet::centre;
case kSpeakerLfe: return AudioChannelSet::LFE;
case kSpeakerLs: return AudioChannelSet::leftSurround;
case kSpeakerRs: return AudioChannelSet::rightSurround;
case kSpeakerLc: return AudioChannelSet::leftCentre;
case kSpeakerRc: return AudioChannelSet::rightCentre;
case kSpeakerCs: return AudioChannelSet::centreSurround;
case kSpeakerSl: return AudioChannelSet::leftSurroundRear;
case kSpeakerSr: return AudioChannelSet::rightSurroundRear;
case (1 << 11): return AudioChannelSet::topMiddle; /* kSpeakerTm */
case kSpeakerTfl: return AudioChannelSet::topFrontLeft;
case kSpeakerTfc: return AudioChannelSet::topFrontCentre;
case kSpeakerTfr: return AudioChannelSet::topFrontRight;
case kSpeakerTrl: return AudioChannelSet::topRearLeft;
case kSpeakerTrc: return AudioChannelSet::topRearCentre;
case kSpeakerTrr: return AudioChannelSet::topRearRight;
case kSpeakerLfe2: return AudioChannelSet::LFE2;
case (1 << 19): return ((arr & kSpeakerC) != 0 ? AudioChannelSet::discreteChannel0 : AudioChannelSet::centre);
case (1 << 20): return AudioChannelSet::ambisonicW; /* kSpeakerW */
case (1 << 21): return AudioChannelSet::ambisonicX; /* kSpeakerX */
case (1 << 22): return AudioChannelSet::ambisonicY; /* kSpeakerY */
case (1 << 23): return AudioChannelSet::ambisonicZ; /* kSpeakerZ */
case (1 << 24): return AudioChannelSet::topSideLeft; /* kSpeakerTsl */
case (1 << 25): return AudioChannelSet::topSideRight; /* kSpeakerTsr */
case (1 << 26): return AudioChannelSet::leftSurroundSide; /* kSpeakerLcs */
case (1 << 27): return AudioChannelSet::rightSurroundSide; /* kSpeakerRcs */
case (1 << 28): return static_cast<AudioChannelSet::ChannelType> ((int)AudioChannelSet::discreteChannel0 + 3); /* kSpeakerBfl */
case (1 << 29): return static_cast<AudioChannelSet::ChannelType> ((int)AudioChannelSet::discreteChannel0 + 4); /* kSpeakerBfc */
case (1 << 30): return static_cast<AudioChannelSet::ChannelType> ((int)AudioChannelSet::discreteChannel0 + 5); /* kSpeakerBfr */
case kSpeakerPl: return AudioChannelSet::wideLeft;
case kSpeakerPr: return AudioChannelSet::wideRight;
default: break;
}
auto channelType = BigInteger (static_cast<int64> (type)).findNextSetBit (0);
// VST3 <-> JUCE layout conversion error: report this bug to the JUCE forum
jassert (channelType >= 33);
return static_cast<AudioChannelSet::ChannelType> (static_cast<int> (AudioChannelSet::discreteChannel0) + 6 + (channelType - 33));
}
static inline Steinberg::Vst::SpeakerArrangement getVst3SpeakerArrangement (const AudioChannelSet& channels) noexcept
{
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 kBFormat;
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;
Steinberg::Vst::SpeakerArrangement result = 0;
Array<AudioChannelSet::ChannelType> types (channels.getChannelTypes());
for (int i = 0; i < types.size(); ++i)
result |= getSpeakerType (channels, types.getReference(i));
return result;
}
static inline AudioChannelSet getChannelSetForSpeakerArrangement (Steinberg::Vst::SpeakerArrangement arr) noexcept
{
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 == kBFormat) 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();
AudioChannelSet result;
BigInteger vstChannels (static_cast<int64> (arr));
for (auto bit = vstChannels.findNextSetBit (0); bit != -1; bit = vstChannels.findNextSetBit (bit + 1))
{
AudioChannelSet::ChannelType channelType = getChannelType (arr, 1ull << static_cast<uint64> (bit));
if (channelType != AudioChannelSet::unknown)
result.addChannel (channelType);
}
// VST3 <-> JUCE layout conversion error: report this bug to the JUCE forum
jassert (result.size() == vstChannels.countNumberOfSetBits());
return result;
}
//==============================================================================
template <class ObjectType>
class ComSmartPtr
{
public:
ComSmartPtr() noexcept : source (nullptr) {}
ComSmartPtr (ObjectType* object, bool autoAddRef = true) noexcept : source (object) { if (source != nullptr && autoAddRef) source->addRef(); }
ComSmartPtr (const ComSmartPtr& other) noexcept : source (other.source) { if (source != nullptr) source->addRef(); }
~ComSmartPtr() { if (source != nullptr) source->release(); }
operator ObjectType*() const noexcept { return source; }
ObjectType* get() const noexcept { return source; }
ObjectType& operator*() const noexcept { return *source; }
ObjectType* operator->() const noexcept { return source; }
ComSmartPtr& operator= (const ComSmartPtr& other) { return operator= (other.source); }
ComSmartPtr& operator= (ObjectType* const newObjectToTakePossessionOf)
{
ComSmartPtr p (newObjectToTakePossessionOf);
std::swap (p.source, source);
return *this;
}
bool operator== (ObjectType* const other) noexcept { return source == other; }
bool operator!= (ObjectType* const other) noexcept { return source != other; }
bool loadFrom (Steinberg::FUnknown* o)
{
*this = nullptr;
return o != nullptr && o->queryInterface (ObjectType::iid, (void**) &source) == Steinberg::kResultOk;
}
bool loadFrom (Steinberg::IPluginFactory* factory, const Steinberg::TUID& uuid)
{
jassert (factory != nullptr);
*this = nullptr;
return factory->createInstance (uuid, ObjectType::iid, (void**) &source) == Steinberg::kResultOk;
}
private:
ObjectType* source;
};
//==============================================================================
class MidiEventList : public Steinberg::Vst::IEventList
{
public:
MidiEventList() {}
virtual ~MidiEventList() {}
JUCE_DECLARE_VST3_COM_REF_METHODS
JUCE_DECLARE_VST3_COM_QUERY_METHODS
//==============================================================================
void clear()
{
events.clearQuick();
}
Steinberg::int32 PLUGIN_API getEventCount() override
{
return (Steinberg::int32) events.size();
}
// NB: This has to cope with out-of-range indexes from some plugins.
Steinberg::tresult PLUGIN_API getEvent (Steinberg::int32 index, Steinberg::Vst::Event& e) override
{
if (isPositiveAndBelow ((int) index, events.size()))
{
e = events.getReference ((int) index);
return Steinberg::kResultTrue;
}
return Steinberg::kResultFalse;
}
Steinberg::tresult PLUGIN_API addEvent (Steinberg::Vst::Event& e) override
{
events.add (e);
return Steinberg::kResultTrue;
}
//==============================================================================
static void toMidiBuffer (MidiBuffer& result, Steinberg::Vst::IEventList& eventList)
{
const int32 numEvents = eventList.getEventCount();
for (Steinberg::int32 i = 0; i < numEvents; ++i)
{
Steinberg::Vst::Event e;
if (eventList.getEvent (i, e) == Steinberg::kResultOk)
{
switch (e.type)
{
case Steinberg::Vst::Event::kNoteOnEvent:
result.addEvent (MidiMessage::noteOn (createSafeChannel (e.noteOn.channel),
createSafeNote (e.noteOn.pitch),
(Steinberg::uint8) denormaliseToMidiValue (e.noteOn.velocity)),
e.sampleOffset);
break;
case Steinberg::Vst::Event::kNoteOffEvent:
result.addEvent (MidiMessage::noteOff (createSafeChannel (e.noteOff.channel),
createSafeNote (e.noteOff.pitch),
(Steinberg::uint8) denormaliseToMidiValue (e.noteOff.velocity)),
e.sampleOffset);
break;
case Steinberg::Vst::Event::kPolyPressureEvent:
result.addEvent (MidiMessage::aftertouchChange (createSafeChannel (e.polyPressure.channel),
createSafeNote (e.polyPressure.pitch),
denormaliseToMidiValue (e.polyPressure.pressure)),
e.sampleOffset);
break;
case Steinberg::Vst::Event::kDataEvent:
result.addEvent (MidiMessage::createSysExMessage (e.data.bytes, (int) e.data.size),
e.sampleOffset);
break;
default:
break;
}
}
}
}
static void toEventList (Steinberg::Vst::IEventList& result, MidiBuffer& midiBuffer)
{
MidiBuffer::Iterator iterator (midiBuffer);
MidiMessage msg;
int midiEventPosition = 0;
enum { maxNumEvents = 2048 }; // Steinberg's Host Checker states that no more than 2048 events are allowed at once
int numEvents = 0;
while (iterator.getNextEvent (msg, midiEventPosition))
{
if (++numEvents > maxNumEvents)
break;
Steinberg::Vst::Event e = { 0 };
if (msg.isNoteOn())
{
e.type = Steinberg::Vst::Event::kNoteOnEvent;
e.noteOn.channel = createSafeChannel (msg.getChannel());
e.noteOn.pitch = createSafeNote (msg.getNoteNumber());
e.noteOn.velocity = normaliseMidiValue (msg.getVelocity());
e.noteOn.length = 0;
e.noteOn.tuning = 0.0f;
e.noteOn.noteId = -1;
}
else if (msg.isNoteOff())
{
e.type = Steinberg::Vst::Event::kNoteOffEvent;
e.noteOff.channel = createSafeChannel (msg.getChannel());
e.noteOff.pitch = createSafeNote (msg.getNoteNumber());
e.noteOff.velocity = normaliseMidiValue (msg.getVelocity());
e.noteOff.tuning = 0.0f;
e.noteOff.noteId = -1;
}
else if (msg.isSysEx())
{
e.type = Steinberg::Vst::Event::kDataEvent;
e.data.bytes = msg.getSysExData();
e.data.size = (uint32) msg.getSysExDataSize();
e.data.type = Steinberg::Vst::DataEvent::kMidiSysEx;
}
else if (msg.isAftertouch())
{
e.type = Steinberg::Vst::Event::kPolyPressureEvent;
e.polyPressure.channel = createSafeChannel (msg.getChannel());
e.polyPressure.pitch = createSafeNote (msg.getNoteNumber());
e.polyPressure.pressure = normaliseMidiValue (msg.getAfterTouchValue());
}
else
{
continue;
}
e.busIndex = 0;
e.sampleOffset = midiEventPosition;
result.addEvent (e);
}
}
private:
Array<Steinberg::Vst::Event, CriticalSection> events;
Atomic<int> refCount;
static Steinberg::int16 createSafeChannel (int channel) noexcept { return (Steinberg::int16) jlimit (0, 15, channel - 1); }
static int createSafeChannel (Steinberg::int16 channel) noexcept { return (int) jlimit (1, 16, channel + 1); }
static Steinberg::int16 createSafeNote (int note) noexcept { return (Steinberg::int16) jlimit (0, 127, note); }
static int createSafeNote (Steinberg::int16 note) noexcept { return jlimit (0, 127, (int) note); }
static float normaliseMidiValue (int value) noexcept { return jlimit (0.0f, 1.0f, (float) value / 127.0f); }
static int denormaliseToMidiValue (float value) noexcept { return roundToInt (jlimit (0.0f, 127.0f, value * 127.0f)); }
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MidiEventList)
};
//==============================================================================
template <typename FloatType>
struct VST3BufferExchange
{
typedef Array<FloatType*> Bus;
typedef Array<Bus> BusMap;
static inline void assignRawPointer (Steinberg::Vst::AudioBusBuffers& vstBuffers, float** raw) { vstBuffers.channelBuffers32 = raw; }
static inline void assignRawPointer (Steinberg::Vst::AudioBusBuffers& vstBuffers, double** raw) { vstBuffers.channelBuffers64 = raw; }
/** Assigns a series of AudioSampleBuffer's channels to an AudioBusBuffers'
@warning For speed, does not check the channel count and offsets
according to the AudioSampleBuffer
*/
static void associateBufferTo (Steinberg::Vst::AudioBusBuffers& vstBuffers,
Bus& bus,
AudioBuffer<FloatType>& buffer,
int numChannels, int channelStartOffset,
int sampleOffset = 0)
{
const int channelEnd = numChannels + channelStartOffset;
jassert (channelEnd >= 0 && channelEnd <= buffer.getNumChannels());
bus.clearQuick();
for (int i = channelStartOffset; i < channelEnd; ++i)
bus.add (buffer.getWritePointer (i, sampleOffset));
assignRawPointer (vstBuffers, (numChannels > 0 ? bus.getRawDataPointer() : nullptr));
vstBuffers.numChannels = numChannels;
vstBuffers.silenceFlags = 0;
}
static void mapArrangementToBuses (int& channelIndexOffset, int index,
Array<Steinberg::Vst::AudioBusBuffers>& result,
BusMap& busMapToUse, const AudioChannelSet& arrangement,
AudioBuffer<FloatType>& source)
{
const int numChansForBus = arrangement.size();
if (index >= result.size())
result.add (Steinberg::Vst::AudioBusBuffers());
if (index >= busMapToUse.size())
busMapToUse.add (Bus());
associateBufferTo (result.getReference (index),
busMapToUse.getReference (index),
source, numChansForBus, channelIndexOffset);
channelIndexOffset += numChansForBus;
}
static inline void mapBufferToBuses (Array<Steinberg::Vst::AudioBusBuffers>& result, BusMap& busMapToUse,
const Array<AudioChannelSet>& arrangements,
AudioBuffer<FloatType>& source)
{
int channelIndexOffset = 0;
for (int i = 0; i < arrangements.size(); ++i)
mapArrangementToBuses (channelIndexOffset, i, result, busMapToUse,
arrangements.getUnchecked (i), source);
}
static inline void mapBufferToBuses (Array<Steinberg::Vst::AudioBusBuffers>& result,
Steinberg::Vst::IAudioProcessor& processor,
BusMap& busMapToUse, bool isInput, int numBuses,
AudioBuffer<FloatType>& source)
{
int channelIndexOffset = 0;
for (int i = 0; i < numBuses; ++i)
mapArrangementToBuses (channelIndexOffset, i,
result, busMapToUse,
getArrangementForBus (&processor, isInput, i),
source);
}
};
template <typename FloatType>
struct VST3FloatAndDoubleBusMapCompositeHelper {};
struct VST3FloatAndDoubleBusMapComposite
{
VST3BufferExchange<float>::BusMap floatVersion;
VST3BufferExchange<double>::BusMap doubleVersion;
template <typename FloatType>
inline typename VST3BufferExchange<FloatType>::BusMap& get() { return VST3FloatAndDoubleBusMapCompositeHelper<FloatType>::get (*this); }
};
template <> struct VST3FloatAndDoubleBusMapCompositeHelper<float>
{
static inline VST3BufferExchange<float>::BusMap& get (VST3FloatAndDoubleBusMapComposite& impl) { return impl.floatVersion; }
};
template <> struct VST3FloatAndDoubleBusMapCompositeHelper<double>
{
static inline VST3BufferExchange<double>::BusMap& get (VST3FloatAndDoubleBusMapComposite& impl) { return impl.doubleVersion; }
};
} // namespace juce

+ 0
- 186
source/modules/juce_audio_processors/format_types/juce_VST3Headers.h View File

@@ -1,186 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
// Wow, those Steinberg guys really don't worry too much about compiler warnings.
#if _MSC_VER
#pragma warning (disable: 4505)
#pragma warning (push, 0)
#pragma warning (disable: 4702)
#elif __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
#pragma clang diagnostic ignored "-Wreorder"
#pragma clang diagnostic ignored "-Wunsequenced"
#pragma clang diagnostic ignored "-Wint-to-pointer-cast"
#pragma clang diagnostic ignored "-Wunused-parameter"
#pragma clang diagnostic ignored "-Wconversion"
#pragma clang diagnostic ignored "-Woverloaded-virtual"
#pragma clang diagnostic ignored "-Wshadow"
#pragma clang diagnostic ignored "-Wdeprecated-register"
#pragma clang diagnostic ignored "-Wunused-function"
#pragma clang diagnostic ignored "-Wsign-conversion"
#pragma clang diagnostic ignored "-Wsign-compare"
#pragma clang diagnostic ignored "-Wdelete-non-virtual-dtor"
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
#pragma clang diagnostic ignored "-Wextra-semi"
#endif
#undef DEVELOPMENT
#define DEVELOPMENT 0 // This avoids a Clang warning in Steinberg code about unused values
/* These files come with the Steinberg VST3 SDK - to get them, you'll need to
visit the Steinberg website and agree to whatever is currently required to
get them.
Then, you'll need to make sure your include path contains your "VST3 SDK"
directory (or whatever you've named it on your machine). The Projucer has
a special box for setting this path.
*/
#if JUCE_VST3HEADERS_INCLUDE_HEADERS_ONLY
#include <base/source/fstring.h>
#include <pluginterfaces/base/conststringtable.h>
#include <pluginterfaces/base/funknown.h>
#include <pluginterfaces/base/ipluginbase.h>
#include <pluginterfaces/base/ustring.h>
#include <pluginterfaces/gui/iplugview.h>
#include <pluginterfaces/gui/iplugviewcontentscalesupport.h>
#include <pluginterfaces/vst/ivstattributes.h>
#include <pluginterfaces/vst/ivstaudioprocessor.h>
#include <pluginterfaces/vst/ivstcomponent.h>
#include <pluginterfaces/vst/ivstcontextmenu.h>
#include <pluginterfaces/vst/ivsteditcontroller.h>
#include <pluginterfaces/vst/ivstevents.h>
#include <pluginterfaces/vst/ivsthostapplication.h>
#include <pluginterfaces/vst/ivstmessage.h>
#include <pluginterfaces/vst/ivstmidicontrollers.h>
#include <pluginterfaces/vst/ivstparameterchanges.h>
#include <pluginterfaces/vst/ivstplugview.h>
#include <pluginterfaces/vst/ivstprocesscontext.h>
#include <pluginterfaces/vst/vsttypes.h>
#include <pluginterfaces/vst/ivstunits.h>
#include <pluginterfaces/vst/ivstmidicontrollers.h>
#include <pluginterfaces/vst/ivstchannelcontextinfo.h>
#include <public.sdk/source/common/memorystream.h>
#include <public.sdk/source/vst/vsteditcontroller.h>
#else
#if JUCE_MINGW
#define _set_abort_behavior(...)
#endif
#include <base/source/baseiids.cpp>
#include <base/source/fatomic.cpp>
#include <base/source/fbuffer.cpp>
#include <base/source/fdebug.cpp>
#include <base/source/fobject.cpp>
#include <base/source/fstreamer.cpp>
#include <base/source/fstring.cpp>
#include <base/source/fthread.cpp>
#include <base/source/updatehandler.cpp>
#include <pluginterfaces/base/conststringtable.cpp>
#include <pluginterfaces/base/funknown.cpp>
#include <pluginterfaces/base/ipluginbase.h>
#include <pluginterfaces/base/ustring.cpp>
#include <pluginterfaces/gui/iplugview.h>
#include <pluginterfaces/gui/iplugviewcontentscalesupport.h>
#include <pluginterfaces/vst/ivstmidicontrollers.h>
#include <pluginterfaces/vst/ivstchannelcontextinfo.h>
#include <public.sdk/source/common/memorystream.cpp>
#include <public.sdk/source/common/pluginview.cpp>
#include <public.sdk/source/vst/vsteditcontroller.cpp>
#include <public.sdk/source/vst/vstbus.cpp>
#include <public.sdk/source/vst/vstinitiids.cpp>
#include <public.sdk/source/vst/vstcomponent.cpp>
#include <public.sdk/source/vst/vstcomponentbase.cpp>
#include <public.sdk/source/vst/vstparameters.cpp>
#include <public.sdk/source/vst/hosting/hostclasses.cpp>
//==============================================================================
namespace Steinberg
{
/** Missing IIDs */
DEF_CLASS_IID (IPluginBase)
DEF_CLASS_IID (IPlugView)
DEF_CLASS_IID (IPlugFrame)
DEF_CLASS_IID (IBStream)
DEF_CLASS_IID (IPluginFactory)
DEF_CLASS_IID (IPluginFactory2)
DEF_CLASS_IID (IPluginFactory3)
DEF_CLASS_IID (IPlugViewContentScaleSupport)
}
#endif //JUCE_VST3HEADERS_INCLUDE_HEADERS_ONLY
#if _MSC_VER
#pragma warning (pop)
#elif __clang__
#pragma clang diagnostic pop
#endif
#if JUCE_WINDOWS
#include <windows.h>
#endif
//==============================================================================
#undef ASSERT
#undef WARNING
#undef PRINTSYSERROR
#undef DEBUGSTR
#undef DBPRT0
#undef DBPRT1
#undef DBPRT2
#undef DBPRT3
#undef DBPRT4
#undef DBPRT5
#undef min
#undef max
#undef MIN
#undef MAX
#undef calloc
#undef free
#undef malloc
#undef realloc
#undef NEW
#undef NEWVEC
#undef VERIFY
#undef VERIFY_IS
#undef VERIFY_NOT
#undef META_CREATE_FUNC
#undef CLASS_CREATE_FUNC
#undef SINGLE_CREATE_FUNC
#undef _META_CLASS
#undef _META_CLASS_IFACE
#undef _META_CLASS_SINGLE
#undef META_CLASS
#undef META_CLASS_IFACE
#undef META_CLASS_SINGLE
#undef SINGLETON
#undef OBJ_METHODS
#undef QUERY_INTERFACE
#undef LICENCE_UID
#undef BEGIN_FACTORY
#undef DEF_CLASS
#undef DEF_CLASS1
#undef DEF_CLASS2
#undef DEF_CLASS_W
#undef END_FACTORY

+ 0
- 2983
source/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp
File diff suppressed because it is too large
View File


+ 0
- 71
source/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.h View File

@@ -1,71 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
#if (JUCE_PLUGINHOST_VST3 && (JUCE_MAC || JUCE_WINDOWS)) || DOXYGEN
/**
Implements a plugin format for VST3s.
*/
class JUCE_API VST3PluginFormat : public AudioPluginFormat
{
public:
/** Constructor */
VST3PluginFormat();
/** Destructor */
~VST3PluginFormat();
//==============================================================================
String getName() const override { return "VST3"; }
void findAllTypesForFile (OwnedArray<PluginDescription>&, const String& fileOrIdentifier) override;
bool fileMightContainThisPluginType (const String& fileOrIdentifier) override;
String getNameOfPluginFromIdentifier (const String& fileOrIdentifier) override;
bool pluginNeedsRescanning (const PluginDescription&) override;
StringArray searchPathsForPlugins (const FileSearchPath&, bool recursive, bool) override;
bool doesPluginStillExist (const PluginDescription&) override;
FileSearchPath getDefaultLocationsToSearch() override;
bool canScanForPlugins() const override { return true; }
private:
void createPluginInstance (const PluginDescription&, double initialSampleRate,
int initialBufferSize, void* userData,
void (*callback) (void*, AudioPluginInstance*, const String&)) override;
bool requiresUnblockedMessageThreadDuringCreation (const PluginDescription&) const noexcept override;
private:
//==============================================================================
void recursiveFileSearch (StringArray&, const File&, bool recursive);
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (VST3PluginFormat)
};
#endif // JUCE_PLUGINHOST_VST3
} // namespace juce

+ 0
- 298
source/modules/juce_audio_processors/format_types/juce_VSTCommon.h View File

@@ -1,298 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
struct SpeakerMappings : private AudioChannelSet // (inheritance only to give easier access to items in the namespace)
{
struct Mapping
{
int32 vst2;
ChannelType channels[13];
bool matches (const Array<ChannelType>& chans) const noexcept
{
const int n = sizeof (channels) / sizeof (ChannelType);
for (int i = 0; i < n; ++i)
{
if (channels[i] == unknown) return (i == chans.size());
if (i == chans.size()) return (channels[i] == unknown);
if (channels[i] != chans.getUnchecked(i))
return false;
}
return true;
}
};
static AudioChannelSet vstArrangementTypeToChannelSet (int32 arr, int fallbackNumChannels)
{
if (arr == vstSpeakerConfigTypeEmpty) return AudioChannelSet::disabled();
else if (arr == vstSpeakerConfigTypeMono) return AudioChannelSet::mono();
else if (arr == vstSpeakerConfigTypeLR) return AudioChannelSet::stereo();
else if (arr == vstSpeakerConfigTypeLRC) return AudioChannelSet::createLCR();
else if (arr == vstSpeakerConfigTypeLRS) return AudioChannelSet::createLRS();
else if (arr == vstSpeakerConfigTypeLRCS) return AudioChannelSet::createLCRS();
else if (arr == vstSpeakerConfigTypeLRCLsRs) return AudioChannelSet::create5point0();
else if (arr == vstSpeakerConfigTypeLRCLfeLsRs) return AudioChannelSet::create5point1();
else if (arr == vstSpeakerConfigTypeLRCLsRsCs) return AudioChannelSet::create6point0();
else if (arr == vstSpeakerConfigTypeLRCLfeLsRsCs) return AudioChannelSet::create6point1();
else if (arr == vstSpeakerConfigTypeLRLsRsSlSr) return AudioChannelSet::create6point0Music();
else if (arr == vstSpeakerConfigTypeLRLfeLsRsSlSr) return AudioChannelSet::create6point1Music();
else if (arr == vstSpeakerConfigTypeLRCLsRsSlSr) return AudioChannelSet::create7point0();
else if (arr == vstSpeakerConfigTypeLRCLsRsLcRc) return AudioChannelSet::create7point0SDDS();
else if (arr == vstSpeakerConfigTypeLRCLfeLsRsSlSr) return AudioChannelSet::create7point1();
else if (arr == vstSpeakerConfigTypeLRCLfeLsRsLcRc) return AudioChannelSet::create7point1SDDS();
else if (arr == vstSpeakerConfigTypeLRLsRs) return AudioChannelSet::quadraphonic();
for (const Mapping* m = getMappings(); m->vst2 != vstSpeakerConfigTypeEmpty; ++m)
{
if (m->vst2 == arr)
{
AudioChannelSet s;
for (int i = 0; m->channels[i] != 0; ++i)
s.addChannel (m->channels[i]);
return s;
}
}
return AudioChannelSet::discreteChannels (fallbackNumChannels);
}
static AudioChannelSet vstArrangementTypeToChannelSet (const VstSpeakerConfiguration& arr)
{
return vstArrangementTypeToChannelSet (arr.type, arr.numberOfChannels);
}
static int32 channelSetToVstArrangementType (AudioChannelSet channels)
{
if (channels == AudioChannelSet::disabled()) return vstSpeakerConfigTypeEmpty;
else if (channels == AudioChannelSet::mono()) return vstSpeakerConfigTypeMono;
else if (channels == AudioChannelSet::stereo()) return vstSpeakerConfigTypeLR;
else if (channels == AudioChannelSet::createLCR()) return vstSpeakerConfigTypeLRC;
else if (channels == AudioChannelSet::createLRS()) return vstSpeakerConfigTypeLRS;
else if (channels == AudioChannelSet::createLCRS()) return vstSpeakerConfigTypeLRCS;
else if (channels == AudioChannelSet::create5point0()) return vstSpeakerConfigTypeLRCLsRs;
else if (channels == AudioChannelSet::create5point1()) return vstSpeakerConfigTypeLRCLfeLsRs;
else if (channels == AudioChannelSet::create6point0()) return vstSpeakerConfigTypeLRCLsRsCs;
else if (channels == AudioChannelSet::create6point1()) return vstSpeakerConfigTypeLRCLfeLsRsCs;
else if (channels == AudioChannelSet::create6point0Music()) return vstSpeakerConfigTypeLRLsRsSlSr;
else if (channels == AudioChannelSet::create6point1Music()) return vstSpeakerConfigTypeLRLfeLsRsSlSr;
else if (channels == AudioChannelSet::create7point0()) return vstSpeakerConfigTypeLRCLsRsSlSr;
else if (channels == AudioChannelSet::create7point0SDDS()) return vstSpeakerConfigTypeLRCLsRsLcRc;
else if (channels == AudioChannelSet::create7point1()) return vstSpeakerConfigTypeLRCLfeLsRsSlSr;
else if (channels == AudioChannelSet::create7point1SDDS()) return vstSpeakerConfigTypeLRCLfeLsRsLcRc;
else if (channels == AudioChannelSet::quadraphonic()) return vstSpeakerConfigTypeLRLsRs;
Array<AudioChannelSet::ChannelType> chans (channels.getChannelTypes());
if (channels == AudioChannelSet::disabled())
return vstSpeakerConfigTypeEmpty;
for (const Mapping* m = getMappings(); m->vst2 != vstSpeakerConfigTypeEmpty; ++m)
if (m->matches (chans))
return m->vst2;
return vstSpeakerConfigTypeUser;
}
class VstSpeakerConfigurationHolder
{
public:
VstSpeakerConfigurationHolder () { clear(); }
VstSpeakerConfigurationHolder (const VstSpeakerConfiguration& vstConfig) { operator= (vstConfig); }
VstSpeakerConfigurationHolder (const VstSpeakerConfigurationHolder& other) { operator= (other.get()); }
VstSpeakerConfigurationHolder (VstSpeakerConfigurationHolder&& other) : storage (static_cast<HeapBlock<VstSpeakerConfiguration>&&> (other.storage)) { other.clear(); }
VstSpeakerConfigurationHolder (const AudioChannelSet& channels)
{
auto numberOfChannels = channels.size();
VstSpeakerConfiguration& dst = *allocate (numberOfChannels);
dst.type = channelSetToVstArrangementType (channels);
dst.numberOfChannels = numberOfChannels;
for (int i = 0; i < dst.numberOfChannels; ++i)
{
VstIndividualSpeakerInfo& speaker = dst.speakers[i];
zeromem (&speaker, sizeof (VstIndividualSpeakerInfo));
speaker.type = getSpeakerType (channels.getTypeOfChannel (i));
}
}
VstSpeakerConfigurationHolder& operator= (const VstSpeakerConfigurationHolder& vstConfig) { return operator=(vstConfig.get()); }
VstSpeakerConfigurationHolder& operator= (const VstSpeakerConfiguration& vstConfig)
{
VstSpeakerConfiguration& dst = *allocate (vstConfig.numberOfChannels);
dst.type = vstConfig.type;
dst.numberOfChannels = vstConfig.numberOfChannels;
for (int i = 0; i < dst.numberOfChannels; ++i)
dst.speakers[i] = vstConfig.speakers[i];
return *this;
}
VstSpeakerConfigurationHolder& operator= (VstSpeakerConfigurationHolder && vstConfig)
{
storage = static_cast<HeapBlock<VstSpeakerConfiguration>&&> (vstConfig.storage);
vstConfig.clear();
return *this;
}
const VstSpeakerConfiguration& get() const { return *storage.get(); }
private:
JUCE_LEAK_DETECTOR (VstSpeakerConfigurationHolder)
HeapBlock<VstSpeakerConfiguration> storage;
VstSpeakerConfiguration* allocate (int numChannels)
{
auto arrangementSize = sizeof (VstSpeakerConfiguration)
+ sizeof (VstIndividualSpeakerInfo) * static_cast<size_t> (jmax (8, numChannels) - 8);
storage.malloc (1, arrangementSize);
return storage.get();
}
void clear()
{
VstSpeakerConfiguration& dst = *allocate (0);
dst.type = vstSpeakerConfigTypeEmpty;
dst.numberOfChannels = 0;
}
};
static const Mapping* getMappings() noexcept
{
static const Mapping mappings[] =
{
{ vstSpeakerConfigTypeMono, { centre, unknown } },
{ vstSpeakerConfigTypeLR, { left, right, unknown } },
{ vstSpeakerConfigTypeLsRs, { leftSurround, rightSurround, unknown } },
{ vstSpeakerConfigTypeLcRc, { leftCentre, rightCentre, unknown } },
{ vstSpeakerConfigTypeSlSr, { leftSurroundRear, rightSurroundRear, unknown } },
{ vstSpeakerConfigTypeCLfe, { centre, LFE, unknown } },
{ vstSpeakerConfigTypeLRC, { left, right, centre, unknown } },
{ vstSpeakerConfigTypeLRS, { left, right, surround, unknown } },
{ vstSpeakerConfigTypeLRCLfe, { left, right, centre, LFE, unknown } },
{ vstSpeakerConfigTypeLRLfeS, { left, right, LFE, surround, unknown } },
{ vstSpeakerConfigTypeLRCS, { left, right, centre, surround, unknown } },
{ vstSpeakerConfigTypeLRLsRs, { left, right, leftSurround, rightSurround, unknown } },
{ vstSpeakerConfigTypeLRCLfeS, { left, right, centre, LFE, surround, unknown } },
{ vstSpeakerConfigTypeLRLfeLsRs, { left, right, LFE, leftSurround, rightSurround, unknown } },
{ vstSpeakerConfigTypeLRCLsRs, { left, right, centre, leftSurround, rightSurround, unknown } },
{ vstSpeakerConfigTypeLRCLfeLsRs, { left, right, centre, LFE, leftSurround, rightSurround, unknown } },
{ vstSpeakerConfigTypeLRCLsRsCs, { left, right, centre, leftSurround, rightSurround, surround, unknown } },
{ vstSpeakerConfigTypeLRLsRsSlSr, { left, right, leftSurround, rightSurround, leftSurroundRear, rightSurroundRear, unknown } },
{ vstSpeakerConfigTypeLRCLfeLsRsCs, { left, right, centre, LFE, leftSurround, rightSurround, surround, unknown } },
{ vstSpeakerConfigTypeLRLfeLsRsSlSr, { left, right, LFE, leftSurround, rightSurround, leftSurroundRear, rightSurroundRear, unknown } },
{ vstSpeakerConfigTypeLRCLsRsLcRc, { left, right, centre, leftSurround, rightSurround, topFrontLeft, topFrontRight, unknown } },
{ vstSpeakerConfigTypeLRCLsRsSlSr, { left, right, centre, leftSurround, rightSurround, leftSurroundRear, rightSurroundRear, unknown } },
{ vstSpeakerConfigTypeLRCLfeLsRsLcRc, { left, right, centre, LFE, leftSurround, rightSurround, topFrontLeft, topFrontRight, unknown } },
{ vstSpeakerConfigTypeLRCLfeLsRsSlSr, { left, right, centre, LFE, leftSurround, rightSurround, leftSurroundRear, rightSurroundRear, unknown } },
{ vstSpeakerConfigTypeLRCLsRsLcRcCs, { left, right, centre, leftSurround, rightSurround, topFrontLeft, topFrontRight, surround, unknown } },
{ vstSpeakerConfigTypeLRCLsRsCsSlSr, { left, right, centre, leftSurround, rightSurround, surround, leftSurroundRear, rightSurroundRear, unknown } },
{ vstSpeakerConfigTypeLRCLfeLsRsLcRcCs, { left, right, centre, LFE, leftSurround, rightSurround, topFrontLeft, topFrontRight, surround, unknown } },
{ vstSpeakerConfigTypeLRCLfeLsRsCsSlSr, { left, right, centre, LFE, leftSurround, rightSurround, surround, leftSurroundRear, rightSurroundRear, unknown } },
{ vstSpeakerConfigTypeLRCLfeLsRsTflTfcTfrTrlTrrLfe2, { left, right, centre, LFE, leftSurround, rightSurround, topFrontLeft, topFrontCentre, topFrontRight, topRearLeft, topRearRight, LFE2, unknown } },
{ vstSpeakerConfigTypeEmpty, { unknown } }
};
return mappings;
}
static inline int32 getSpeakerType (AudioChannelSet::ChannelType type) noexcept
{
switch (type)
{
case AudioChannelSet::left: return vstIndividualSpeakerTypeLeft;
case AudioChannelSet::right: return vstIndividualSpeakerTypeRight;
case AudioChannelSet::centre: return vstIndividualSpeakerTypeCentre;
case AudioChannelSet::LFE: return vstIndividualSpeakerTypeLFE;
case AudioChannelSet::leftSurround: return vstIndividualSpeakerTypeLeftSurround;
case AudioChannelSet::rightSurround: return vstIndividualSpeakerTypeRightSurround;
case AudioChannelSet::leftCentre: return vstIndividualSpeakerTypeLeftCentre;
case AudioChannelSet::rightCentre: return vstIndividualSpeakerTypeRightCentre;
case AudioChannelSet::surround: return vstIndividualSpeakerTypeSurround;
case AudioChannelSet::leftSurroundRear: return vstIndividualSpeakerTypeLeftRearSurround;
case AudioChannelSet::rightSurroundRear: return vstIndividualSpeakerTypeRightRearSurround;
case AudioChannelSet::topMiddle: return vstIndividualSpeakerTypeTopMiddle;
case AudioChannelSet::topFrontLeft: return vstIndividualSpeakerTypeTopFrontLeft;
case AudioChannelSet::topFrontCentre: return vstIndividualSpeakerTypeTopFrontCentre;
case AudioChannelSet::topFrontRight: return vstIndividualSpeakerTypeTopFrontRight;
case AudioChannelSet::topRearLeft: return vstIndividualSpeakerTypeTopRearLeft;
case AudioChannelSet::topRearCentre: return vstIndividualSpeakerTypeTopRearCentre;
case AudioChannelSet::topRearRight: return vstIndividualSpeakerTypeTopRearRight;
case AudioChannelSet::LFE2: return vstIndividualSpeakerTypeLFE2;
default: break;
}
return 0;
}
static inline AudioChannelSet::ChannelType getChannelType (int32 type) noexcept
{
switch (type)
{
case vstIndividualSpeakerTypeLeft: return AudioChannelSet::left;
case vstIndividualSpeakerTypeRight: return AudioChannelSet::right;
case vstIndividualSpeakerTypeCentre: return AudioChannelSet::centre;
case vstIndividualSpeakerTypeLFE: return AudioChannelSet::LFE;
case vstIndividualSpeakerTypeLeftSurround: return AudioChannelSet::leftSurround;
case vstIndividualSpeakerTypeRightSurround: return AudioChannelSet::rightSurround;
case vstIndividualSpeakerTypeLeftCentre: return AudioChannelSet::leftCentre;
case vstIndividualSpeakerTypeRightCentre: return AudioChannelSet::rightCentre;
case vstIndividualSpeakerTypeSurround: return AudioChannelSet::surround;
case vstIndividualSpeakerTypeLeftRearSurround: return AudioChannelSet::leftSurroundRear;
case vstIndividualSpeakerTypeRightRearSurround: return AudioChannelSet::rightSurroundRear;
case vstIndividualSpeakerTypeTopMiddle: return AudioChannelSet::topMiddle;
case vstIndividualSpeakerTypeTopFrontLeft: return AudioChannelSet::topFrontLeft;
case vstIndividualSpeakerTypeTopFrontCentre: return AudioChannelSet::topFrontCentre;
case vstIndividualSpeakerTypeTopFrontRight: return AudioChannelSet::topFrontRight;
case vstIndividualSpeakerTypeTopRearLeft: return AudioChannelSet::topRearLeft;
case vstIndividualSpeakerTypeTopRearCentre: return AudioChannelSet::topRearCentre;
case vstIndividualSpeakerTypeTopRearRight: return AudioChannelSet::topRearRight;
case vstIndividualSpeakerTypeLFE2: return AudioChannelSet::LFE2;
default: break;
}
return AudioChannelSet::unknown;
}
};
} // namespace juce

+ 0
- 485
source/modules/juce_audio_processors/format_types/juce_VSTInterface.h View File

@@ -1,485 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
#define JUCE_VSTINTERFACE_H_INCLUDED
using namespace juce;
#if JUCE_MSVC
#define VSTINTERFACECALL __cdecl
#pragma pack(push)
#pragma pack(8)
#elif JUCE_MAC || JUCE_IOS
#define VSTINTERFACECALL
#if JUCE_64BIT
#pragma options align=power
#else
#pragma options align=mac68k
#endif
#else
#define VSTINTERFACECALL
#pragma pack(push, 8)
#endif
const int32 juceVstInterfaceVersion = 2400;
const int32 juceVstInterfaceIdentifier = 0x56737450; // The "magic" identifier in the SDK is 'VstP'.
//==============================================================================
struct VstEffectInterface
{
int32 interfaceIdentifier;
pointer_sized_int (VSTINTERFACECALL* dispatchFunction) (VstEffectInterface*, int32 op, int32 index, pointer_sized_int value, void* ptr, float opt);
void (VSTINTERFACECALL* processAudioFunction) (VstEffectInterface*, float** inputs, float** outputs, int32 numSamples);
void (VSTINTERFACECALL* setParameterValueFunction) (VstEffectInterface*, int32 parameterIndex, float value);
float (VSTINTERFACECALL* getParameterValueFunction) (VstEffectInterface*, int32 parameterIndex);
int32 numPrograms;
int32 numParameters;
int32 numInputChannels;
int32 numOutputChannels;
int32 flags;
pointer_sized_int hostSpace1;
pointer_sized_int hostSpace2;
int32 latency;
int32 deprecated1;
int32 deprecated2;
float deprecated3;
void* effectPointer;
void* userPointer;
int32 plugInIdentifier;
int32 plugInVersion;
void (VSTINTERFACECALL* processAudioInplaceFunction) (VstEffectInterface*, float** inputs, float** outputs, int32 numSamples);
void (VSTINTERFACECALL* processDoubleAudioInplaceFunction) (VstEffectInterface*, double** inputs, double** outputs, int32 numSamples);
char emptySpace[56];
};
typedef pointer_sized_int (VSTINTERFACECALL* VstHostCallback) (VstEffectInterface*, int32 op, int32 index, pointer_sized_int value, void* ptr, float opt);
enum VstEffectInterfaceFlags
{
vstEffectFlagHasEditor = 1,
vstEffectFlagInplaceAudio = 16,
vstEffectFlagDataInChunks = 32,
vstEffectFlagIsSynth = 256,
vstEffectFlagInplaceDoubleAudio = 4096
};
//==============================================================================
enum VstHostToPlugInOpcodes
{
plugInOpcodeOpen,
plugInOpcodeClose,
plugInOpcodeSetCurrentProgram,
plugInOpcodeGetCurrentProgram,
plugInOpcodeSetCurrentProgramName,
plugInOpcodeGetCurrentProgramName,
plugInOpcodeGetParameterLabel,
plugInOpcodeGetParameterText,
plugInOpcodeGetParameterName,
plugInOpcodeSetSampleRate = plugInOpcodeGetParameterName + 2,
plugInOpcodeSetBlockSize,
plugInOpcodeResumeSuspend,
plugInOpcodeGetEditorBounds,
plugInOpcodeOpenEditor,
plugInOpcodeCloseEditor,
plugInOpcodeDrawEditor,
plugInOpcodeGetMouse,
plugInOpcodeEditorIdle = plugInOpcodeGetMouse + 2,
plugInOpcodeeffEditorTop,
plugInOpcodeSleepEditor,
plugInOpcodeIdentify,
plugInOpcodeGetData,
plugInOpcodeSetData,
plugInOpcodePreAudioProcessingEvents,
plugInOpcodeIsParameterAutomatable,
plugInOpcodeParameterValueForText,
plugInOpcodeGetProgramName = plugInOpcodeParameterValueForText + 2,
plugInOpcodeConnectInput = plugInOpcodeGetProgramName + 2,
plugInOpcodeConnectOutput,
plugInOpcodeGetInputPinProperties,
plugInOpcodeGetOutputPinProperties,
plugInOpcodeGetPlugInCategory,
plugInOpcodeSetSpeakerConfiguration = plugInOpcodeGetPlugInCategory + 7,
plugInOpcodeSetBypass = plugInOpcodeSetSpeakerConfiguration + 2,
plugInOpcodeGetPlugInName,
plugInOpcodeGetManufacturerName = plugInOpcodeGetPlugInName + 2,
plugInOpcodeGetManufacturerProductName,
plugInOpcodeGetManufacturerVersion,
plugInOpcodeManufacturerSpecific,
plugInOpcodeCanPlugInDo,
plugInOpcodeGetTailSize,
plugInOpcodeIdle,
plugInOpcodeKeyboardFocusRequired = plugInOpcodeIdle + 4,
plugInOpcodeGetVstInterfaceVersion,
plugInOpcodeGetCurrentMidiProgram = plugInOpcodeGetVstInterfaceVersion + 5,
plugInOpcodeGetSpeakerArrangement = plugInOpcodeGetCurrentMidiProgram + 6,
plugInOpcodeNextPlugInUniqueID,
plugInOpcodeStartProcess,
plugInOpcodeStopProcess,
plugInOpcodeSetNumberOfSamplesToProcess,
plugInOpcodeSetSampleFloatType = plugInOpcodeSetNumberOfSamplesToProcess + 4,
pluginOpcodeGetNumMidiInputChannels,
pluginOpcodeGetNumMidiOutputChannels,
plugInOpcodeMaximum = pluginOpcodeGetNumMidiOutputChannels
};
enum VstPlugInToHostOpcodes
{
hostOpcodeParameterChanged,
hostOpcodeVstVersion,
hostOpcodeCurrentId,
hostOpcodeIdle,
hostOpcodePinConnected,
hostOpcodePlugInWantsMidi = hostOpcodePinConnected + 2,
hostOpcodeGetTimingInfo,
hostOpcodePreAudioProcessingEvents,
hostOpcodeSetTime,
hostOpcodeTempoAt,
hostOpcodeGetNumberOfAutomatableParameters,
hostOpcodeGetParameterInterval,
hostOpcodeIOModified,
hostOpcodeNeedsIdle,
hostOpcodeWindowSize,
hostOpcodeGetSampleRate,
hostOpcodeGetBlockSize,
hostOpcodeGetInputLatency,
hostOpcodeGetOutputLatency,
hostOpcodeGetPreviousPlugIn,
hostOpcodeGetNextPlugIn,
hostOpcodeWillReplace,
hostOpcodeGetCurrentAudioProcessingLevel,
hostOpcodeGetAutomationState,
hostOpcodeOfflineStart,
hostOpcodeOfflineReadSource,
hostOpcodeOfflineWrite,
hostOpcodeOfflineGetCurrentPass,
hostOpcodeOfflineGetCurrentMetaPass,
hostOpcodeSetOutputSampleRate,
hostOpcodeGetOutputSpeakerConfiguration,
hostOpcodeGetManufacturerName,
hostOpcodeGetProductName,
hostOpcodeGetManufacturerVersion,
hostOpcodeManufacturerSpecific,
hostOpcodeSetIcon,
hostOpcodeCanHostDo,
hostOpcodeGetLanguage,
hostOpcodeOpenEditorWindow,
hostOpcodeCloseEditorWindow,
hostOpcodeGetDirectory,
hostOpcodeUpdateView,
hostOpcodeParameterChangeGestureBegin,
hostOpcodeParameterChangeGestureEnd,
};
//==============================================================================
enum VstProcessingSampleType
{
vstProcessingSampleTypeFloat,
vstProcessingSampleTypeDouble
};
//==============================================================================
// These names must be identical to the Steinberg SDK so JUCE users can set
// exactly what they want.
enum VstPlugInCategory
{
kPlugCategUnknown,
kPlugCategEffect,
kPlugCategSynth,
kPlugCategAnalysis,
kPlugCategMastering,
kPlugCategSpacializer,
kPlugCategRoomFx,
kPlugSurroundFx,
kPlugCategRestoration,
kPlugCategOfflineProcess,
kPlugCategShell,
kPlugCategGenerator
};
//==============================================================================
struct VstEditorBounds
{
int16 upper;
int16 leftmost;
int16 lower;
int16 rightmost;
};
//==============================================================================
enum VstMaxStringLengths
{
vstMaxNameLength = 64,
vstMaxParameterOrPinLabelLength = 64,
vstMaxParameterOrPinShortLabelLength = 8,
vstMaxCategoryLength = 24,
vstMaxManufacturerStringLength = 64,
vstMaxPlugInNameStringLength = 64
};
//==============================================================================
struct VstPinInfo
{
char text[vstMaxParameterOrPinLabelLength];
int32 flags;
int32 configurationType;
char shortText[vstMaxParameterOrPinShortLabelLength];
char unused[48];
};
enum VstPinInfoFlags
{
vstPinInfoFlagIsActive = 1,
vstPinInfoFlagIsStereo = 2,
vstPinInfoFlagValid = 4
};
//==============================================================================
struct VstEvent
{
int32 type;
int32 size;
int32 sampleOffset;
int32 flags;
char content[16];
};
enum VstEventTypes
{
vstMidiEventType = 1,
vstSysExEventType = 6
};
struct VstEventBlock
{
int32 numberOfEvents;
pointer_sized_int future;
VstEvent* events[2];
};
struct VstMidiEvent
{
int32 type;
int32 size;
int32 sampleOffset;
int32 flags;
int32 noteSampleLength;
int32 noteSampleOffset;
char midiData[4];
char tuning;
char noteVelocityOff;
char future1;
char future2;
};
enum VstMidiEventFlags
{
vstMidiEventIsRealtime = 1
};
struct VstSysExEvent
{
int32 type;
int32 size;
int32 offsetSamples;
int32 flags;
int32 sysExDumpSize;
pointer_sized_int future1;
char* sysExDump;
pointer_sized_int future2;
};
//==============================================================================
struct VstTimingInformation
{
double samplePosition;
double sampleRate;
double systemTimeNanoseconds;
double musicalPosition;
double tempoBPM;
double lastBarPosition;
double loopStartPosition;
double loopEndPosition;
int32 timeSignatureNumerator;
int32 timeSignatureDenominator;
int32 smpteOffset;
int32 smpteRate;
int32 samplesToNearestClock;
int32 flags;
};
enum VstTimingInformationFlags
{
vstTimingInfoFlagTransportChanged = 1,
vstTimingInfoFlagCurrentlyPlaying = 2,
vstTimingInfoFlagLoopActive = 4,
vstTimingInfoFlagCurrentlyRecording = 8,
vstTimingInfoFlagAutomationWriteModeActive = 64,
vstTimingInfoFlagAutomationReadModeActive = 128,
vstTimingInfoFlagNanosecondsValid = 256,
vstTimingInfoFlagMusicalPositionValid = 512,
vstTimingInfoFlagTempoValid = 1024,
vstTimingInfoFlagLastBarPositionValid = 2048,
vstTimingInfoFlagLoopPositionValid = 4096,
vstTimingInfoFlagTimeSignatureValid = 8192,
vstTimingInfoFlagSmpteValid = 16384,
vstTimingInfoFlagNearestClockValid = 32768
};
//==============================================================================
enum VstSmpteRates
{
vstSmpteRateFps24,
vstSmpteRateFps25,
vstSmpteRateFps2997,
vstSmpteRateFps30,
vstSmpteRateFps2997drop,
vstSmpteRateFps30drop,
vstSmpteRate16mmFilm,
vstSmpteRate35mmFilm,
vstSmpteRateFps239 = vstSmpteRate35mmFilm + 3,
vstSmpteRateFps249 ,
vstSmpteRateFps599,
vstSmpteRateFps60
};
//==============================================================================
struct VstIndividualSpeakerInfo
{
float azimuthalAngle;
float elevationAngle;
float radius;
float reserved;
char label[vstMaxNameLength];
int32 type;
char unused[28];
};
enum VstIndividualSpeakerType
{
vstIndividualSpeakerTypeUndefined = 0x7fffffff,
vstIndividualSpeakerTypeMono = 0,
vstIndividualSpeakerTypeLeft,
vstIndividualSpeakerTypeRight,
vstIndividualSpeakerTypeCentre,
vstIndividualSpeakerTypeLFE,
vstIndividualSpeakerTypeLeftSurround,
vstIndividualSpeakerTypeRightSurround,
vstIndividualSpeakerTypeLeftCentre,
vstIndividualSpeakerTypeRightCentre,
vstIndividualSpeakerTypeSurround,
vstIndividualSpeakerTypeCentreSurround = vstIndividualSpeakerTypeSurround,
vstIndividualSpeakerTypeLeftRearSurround,
vstIndividualSpeakerTypeRightRearSurround,
vstIndividualSpeakerTypeTopMiddle,
vstIndividualSpeakerTypeTopFrontLeft,
vstIndividualSpeakerTypeTopFrontCentre,
vstIndividualSpeakerTypeTopFrontRight,
vstIndividualSpeakerTypeTopRearLeft,
vstIndividualSpeakerTypeTopRearCentre,
vstIndividualSpeakerTypeTopRearRight,
vstIndividualSpeakerTypeLFE2
};
struct VstSpeakerConfiguration
{
int32 type;
int32 numberOfChannels;
VstIndividualSpeakerInfo speakers[8];
};
enum VstSpeakerConfigurationType
{
vstSpeakerConfigTypeUser = -2,
vstSpeakerConfigTypeEmpty = -1,
vstSpeakerConfigTypeMono = 0,
vstSpeakerConfigTypeLR,
vstSpeakerConfigTypeLsRs,
vstSpeakerConfigTypeLcRc,
vstSpeakerConfigTypeSlSr,
vstSpeakerConfigTypeCLfe,
vstSpeakerConfigTypeLRC,
vstSpeakerConfigTypeLRS,
vstSpeakerConfigTypeLRCLfe,
vstSpeakerConfigTypeLRLfeS,
vstSpeakerConfigTypeLRCS,
vstSpeakerConfigTypeLRLsRs,
vstSpeakerConfigTypeLRCLfeS,
vstSpeakerConfigTypeLRLfeLsRs,
vstSpeakerConfigTypeLRCLsRs,
vstSpeakerConfigTypeLRCLfeLsRs,
vstSpeakerConfigTypeLRCLsRsCs,
vstSpeakerConfigTypeLRLsRsSlSr,
vstSpeakerConfigTypeLRCLfeLsRsCs,
vstSpeakerConfigTypeLRLfeLsRsSlSr,
vstSpeakerConfigTypeLRCLsRsLcRc,
vstSpeakerConfigTypeLRCLsRsSlSr,
vstSpeakerConfigTypeLRCLfeLsRsLcRc,
vstSpeakerConfigTypeLRCLfeLsRsSlSr,
vstSpeakerConfigTypeLRCLsRsLcRcCs,
vstSpeakerConfigTypeLRCLsRsCsSlSr,
vstSpeakerConfigTypeLRCLfeLsRsLcRcCs,
vstSpeakerConfigTypeLRCLfeLsRsCsSlSr,
vstSpeakerConfigTypeLRCLfeLsRsTflTfcTfrTrlTrrLfe2
};
#if JUCE_BIG_ENDIAN
#define JUCE_MULTICHAR_CONSTANT(a, b, c, d) (a | (((uint32) b) << 8) | (((uint32) c) << 16) | (((uint32) d) << 24))
#else
#define JUCE_MULTICHAR_CONSTANT(a, b, c, d) (d | (((uint32) c) << 8) | (((uint32) b) << 16) | (((uint32) a) << 24))
#endif
enum PresonusExtensionConstants
{
presonusVendorID = JUCE_MULTICHAR_CONSTANT ('P', 'r', 'e', 'S'),
presonusSetContentScaleFactor = JUCE_MULTICHAR_CONSTANT ('A', 'e', 'C', 's')
};
//==============================================================================
struct vst2FxBank
{
int32 magic1;
int32 size;
int32 magic2;
int32 version1;
int32 fxID;
int32 version2;
int32 elements;
int32 current;
char shouldBeZero[124];
int32 chunkSize;
char chunk[1];
};
#if JUCE_MSVC
#pragma pack(pop)
#elif JUCE_MAC || JUCE_IOS
#pragma options align=reset
#else
#pragma pack(pop)
#endif

+ 0
- 191
source/modules/juce_audio_processors/format_types/juce_VSTMidiEventList.h View File

@@ -1,191 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
// NB: this must come first, *before* the header-guard.
#ifdef JUCE_VSTINTERFACE_H_INCLUDED
namespace juce
{
//==============================================================================
/** Holds a set of VSTMidiEvent objects and makes it easy to add
events to the list.
This is used by both the VST hosting code and the plugin wrapper.
*/
class VSTMidiEventList
{
public:
//==============================================================================
VSTMidiEventList()
: numEventsUsed (0), numEventsAllocated (0)
{
}
~VSTMidiEventList()
{
freeEvents();
}
//==============================================================================
void clear()
{
numEventsUsed = 0;
if (events != nullptr)
events->numberOfEvents = 0;
}
void addEvent (const void* const midiData, const int numBytes, const int frameOffset)
{
ensureSize (numEventsUsed + 1);
VstMidiEvent* const e = (VstMidiEvent*) (events->events [numEventsUsed]);
events->numberOfEvents = ++numEventsUsed;
if (numBytes <= 4)
{
if (e->type == vstSysExEventType)
{
delete[] (((VstSysExEvent*) e)->sysExDump);
e->type = vstMidiEventType;
e->size = sizeof (VstMidiEvent);
e->noteSampleLength = 0;
e->noteSampleOffset = 0;
e->tuning = 0;
e->noteVelocityOff = 0;
}
e->sampleOffset = frameOffset;
memcpy (e->midiData, midiData, (size_t) numBytes);
}
else
{
VstSysExEvent* const se = (VstSysExEvent*) e;
if (se->type == vstSysExEventType)
delete[] se->sysExDump;
se->sysExDump = new char [(size_t) numBytes];
memcpy (se->sysExDump, midiData, (size_t) numBytes);
se->type = vstSysExEventType;
se->size = sizeof (VstSysExEvent);
se->offsetSamples = frameOffset;
se->flags = 0;
se->sysExDumpSize = numBytes;
se->future1 = 0;
se->future2 = 0;
}
}
//==============================================================================
// Handy method to pull the events out of an event buffer supplied by the host
// or plugin.
static void addEventsToMidiBuffer (const VstEventBlock* events, MidiBuffer& dest)
{
for (int i = 0; i < events->numberOfEvents; ++i)
{
const VstEvent* const e = events->events[i];
if (e != nullptr)
{
if (e->type == vstMidiEventType)
{
dest.addEvent ((const juce::uint8*) ((const VstMidiEvent*) e)->midiData,
4, e->sampleOffset);
}
else if (e->type == vstSysExEventType)
{
dest.addEvent ((const juce::uint8*) ((const VstSysExEvent*) e)->sysExDump,
(int) ((const VstSysExEvent*) e)->sysExDumpSize,
e->sampleOffset);
}
}
}
}
//==============================================================================
void ensureSize (int numEventsNeeded)
{
if (numEventsNeeded > numEventsAllocated)
{
numEventsNeeded = (numEventsNeeded + 32) & ~31;
const size_t size = 20 + sizeof (VstEvent*) * (size_t) numEventsNeeded;
if (events == nullptr)
events.calloc (size, 1);
else
events.realloc (size, 1);
for (int i = numEventsAllocated; i < numEventsNeeded; ++i)
events->events[i] = allocateVSTEvent();
numEventsAllocated = numEventsNeeded;
}
}
void freeEvents()
{
if (events != nullptr)
{
for (int i = numEventsAllocated; --i >= 0;)
freeVSTEvent (events->events[i]);
events.free();
numEventsUsed = 0;
numEventsAllocated = 0;
}
}
//==============================================================================
HeapBlock<VstEventBlock> events;
private:
int numEventsUsed, numEventsAllocated;
static VstEvent* allocateVSTEvent()
{
auto e = (VstEvent*) std::calloc (1, sizeof (VstMidiEvent) > sizeof (VstSysExEvent) ? sizeof (VstMidiEvent)
: sizeof (VstSysExEvent));
e->type = vstMidiEventType;
e->size = sizeof (VstMidiEvent);
return e;
}
static void freeVSTEvent (VstEvent* e)
{
if (e->type == vstSysExEventType)
delete[] (((VstSysExEvent*) e)->sysExDump);
std::free (e);
}
};
} // namespace juce
#endif // JUCE_VSTINTERFACE_H_INCLUDED

+ 0
- 2972
source/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp
File diff suppressed because it is too large
View File


+ 0
- 132
source/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.h View File

@@ -1,132 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
#if (JUCE_PLUGINHOST_VST || DOXYGEN)
namespace juce
{
//==============================================================================
/**
Implements a plugin format manager for VSTs.
*/
class JUCE_API VSTPluginFormat : public AudioPluginFormat
{
public:
//==============================================================================
VSTPluginFormat();
~VSTPluginFormat();
//==============================================================================
/** Attempts to retrieve the VSTXML data from a plugin.
Will return nullptr if the plugin isn't a VST, or if it doesn't have any VSTXML.
*/
static const XmlElement* getVSTXML (AudioPluginInstance* plugin);
/** Attempts to reload a VST plugin's state from some FXB or FXP data. */
static bool loadFromFXBFile (AudioPluginInstance* plugin, const void* data, size_t dataSize);
/** Attempts to save a VST's state to some FXP or FXB data. */
static bool saveToFXBFile (AudioPluginInstance* plugin, MemoryBlock& result, bool asFXB);
/** Attempts to get a VST's state as a chunk of memory. */
static bool getChunkData (AudioPluginInstance* plugin, MemoryBlock& result, bool isPreset);
/** Attempts to set a VST's state from a chunk of memory. */
static bool setChunkData (AudioPluginInstance* plugin, const void* data, int size, bool isPreset);
/** Given a suitable function pointer to a VSTPluginMain function, this will attempt to
instantiate and return a plugin for it.
*/
static AudioPluginInstance* createCustomVSTFromMainCall (void* entryPointFunction,
double initialSampleRate,
int initialBufferSize);
//==============================================================================
/** Base class for some extra functions that can be attached to a VST plugin instance. */
class ExtraFunctions
{
public:
virtual ~ExtraFunctions() {}
/** This should return 10000 * the BPM at this position in the current edit. */
virtual int64 getTempoAt (int64 samplePos) = 0;
/** This should return the host's automation state.
@returns 0 = not supported, 1 = off, 2 = read, 3 = write, 4 = read/write
*/
virtual int getAutomationState() = 0;
};
/** Provides an ExtraFunctions callback object for a plugin to use.
The plugin will take ownership of the object and will delete it automatically.
*/
static void setExtraFunctions (AudioPluginInstance* plugin, ExtraFunctions* functions);
//==============================================================================
/** This simply calls directly to the VST's AEffect::dispatcher() function. */
static pointer_sized_int JUCE_CALLTYPE dispatcher (AudioPluginInstance*, int32, int32, pointer_sized_int, void*, float);
/** Given a VstEffectInterface* (aka vst::AEffect*), this will return the juce AudioPluginInstance
that is being used to wrap it
*/
static AudioPluginInstance* getPluginInstanceFromVstEffectInterface (void* aEffect);
//==============================================================================
String getName() const override { return "VST"; }
void findAllTypesForFile (OwnedArray<PluginDescription>&, const String& fileOrIdentifier) override;
bool fileMightContainThisPluginType (const String& fileOrIdentifier) override;
String getNameOfPluginFromIdentifier (const String& fileOrIdentifier) override;
bool pluginNeedsRescanning (const PluginDescription&) override;
StringArray searchPathsForPlugins (const FileSearchPath&, bool recursive, bool) override;
bool doesPluginStillExist (const PluginDescription&) override;
FileSearchPath getDefaultLocationsToSearch() override;
bool canScanForPlugins() const override { return true; }
/** Can be overridden to receive a callback when each member of a shell plugin is about to be
tested during a call to findAllTypesForFile().
Only the name and uid members of the PluginDescription are guaranteed to be valid when
this is called.
*/
virtual void aboutToScanVSTShellPlugin (const PluginDescription&);
private:
//==============================================================================
void createPluginInstance (const PluginDescription&, double initialSampleRate,
int initialBufferSize, void* userData,
void (*callback) (void*, AudioPluginInstance*, const String&)) override;
bool requiresUnblockedMessageThreadDuringCreation (const PluginDescription&) const noexcept override;
private:
void recursiveFileSearch (StringArray&, const File&, bool recursive);
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (VSTPluginFormat)
};
} // namespace juce
#endif

+ 0
- 185
source/modules/juce_audio_processors/juce_audio_processors.cpp View File

@@ -1,185 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
#ifdef JUCE_AUDIO_PROCESSORS_H_INCLUDED
/* When you add this cpp file to your project, you mustn't include it in a file where you've
already included any other headers - just put it inside a file on its own, possibly with your config
flags preceding it, but don't include anything else. That also includes avoiding any automatic prefix
header files that the compiler may be using.
*/
#error "Incorrect use of JUCE cpp file"
#endif
#define JUCE_CORE_INCLUDE_NATIVE_HEADERS 1
#define JUCE_CORE_INCLUDE_OBJC_HELPERS 1
#include "juce_audio_processors.h"
#include <juce_gui_extra/juce_gui_extra.h>
//==============================================================================
#if JUCE_MAC
#if JUCE_SUPPORT_CARBON \
&& ((JUCE_PLUGINHOST_VST || JUCE_PLUGINHOST_AU) \
|| ! (defined (MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6))
#include <Carbon/Carbon.h>
#include "../juce_gui_extra/native/juce_mac_CarbonViewWrapperComponent.h"
#endif
#endif
#if JUCE_PLUGINHOST_VST && JUCE_LINUX && ! JUCE_AUDIOPROCESSOR_NO_GUI
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#undef KeyPress
#endif
#if ! JUCE_WINDOWS && ! JUCE_MAC
#undef JUCE_PLUGINHOST_VST3
#define JUCE_PLUGINHOST_VST3 0
#endif
#if JUCE_PLUGINHOST_AU && (JUCE_MAC || JUCE_IOS)
#include <AudioUnit/AudioUnit.h>
#endif
//==============================================================================
namespace juce
{
static inline bool arrayContainsPlugin (const OwnedArray<PluginDescription>& list,
const PluginDescription& desc)
{
for (auto* p : list)
if (p->isDuplicateOf (desc))
return true;
return false;
}
#if JUCE_MAC || JUCE_IOS
#if JUCE_IOS
#define JUCE_IOS_MAC_VIEW UIView
typedef UIViewComponent ViewComponentBaseClass;
#else
#define JUCE_IOS_MAC_VIEW NSView
typedef NSViewComponent ViewComponentBaseClass;
#endif
//==============================================================================
struct AutoResizingNSViewComponent : public ViewComponentBaseClass,
private AsyncUpdater
{
AutoResizingNSViewComponent();
void childBoundsChanged (Component*) override;
void handleAsyncUpdate() override;
bool recursive;
};
//==============================================================================
struct AutoResizingNSViewComponentWithParent : public AutoResizingNSViewComponent,
private Timer
{
AutoResizingNSViewComponentWithParent();
JUCE_IOS_MAC_VIEW* getChildView() const;
void timerCallback() override;
};
//==============================================================================
AutoResizingNSViewComponent::AutoResizingNSViewComponent()
: recursive (false) {}
void AutoResizingNSViewComponent::childBoundsChanged (Component*) override
{
if (recursive)
{
triggerAsyncUpdate();
}
else
{
recursive = true;
resizeToFitView();
recursive = true;
}
}
void AutoResizingNSViewComponent::handleAsyncUpdate() override
{
resizeToFitView();
}
//==============================================================================
AutoResizingNSViewComponentWithParent::AutoResizingNSViewComponentWithParent()
{
JUCE_IOS_MAC_VIEW* v = [[JUCE_IOS_MAC_VIEW alloc] init];
setView (v);
[v release];
startTimer (30);
}
JUCE_IOS_MAC_VIEW* AutoResizingNSViewComponentWithParent::getChildView() const
{
if (JUCE_IOS_MAC_VIEW* parent = (JUCE_IOS_MAC_VIEW*) getView())
if ([[parent subviews] count] > 0)
return [[parent subviews] objectAtIndex: 0];
return nil;
}
void AutoResizingNSViewComponentWithParent::timerCallback() override
{
if (JUCE_IOS_MAC_VIEW* child = getChildView())
{
stopTimer();
setView (child);
}
}
#endif
} // namespace juce
#if JUCE_CLANG
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
#endif
#include "format/juce_AudioPluginFormat.cpp"
#include "format/juce_AudioPluginFormatManager.cpp"
#include "processors/juce_AudioProcessor.cpp"
#include "processors/juce_AudioProcessorGraph.cpp"
#if ! JUCE_AUDIOPROCESSOR_NO_GUI
#include "processors/juce_AudioProcessorEditor.cpp"
#include "processors/juce_GenericAudioProcessorEditor.cpp"
#endif
#include "processors/juce_PluginDescription.cpp"
#include "format_types/juce_LADSPAPluginFormat.cpp"
#include "format_types/juce_VSTPluginFormat.cpp"
#include "format_types/juce_VST3PluginFormat.cpp"
#include "format_types/juce_AudioUnitPluginFormat.mm"
#include "scanning/juce_KnownPluginList.cpp"
#include "scanning/juce_PluginDirectoryScanner.cpp"
#include "scanning/juce_PluginListComponent.cpp"
#include "utilities/juce_AudioProcessorParameters.cpp"
#include "utilities/juce_AudioProcessorValueTreeState.cpp"

+ 0
- 124
source/modules/juce_audio_processors/juce_audio_processors.h View File

@@ -1,124 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
/*******************************************************************************
The block below describes the properties of this module, and is read by
the Projucer to automatically generate project code that uses it.
For details about the syntax and how to create or use a module, see the
JUCE Module Format.txt file.
BEGIN_JUCE_MODULE_DECLARATION
ID: juce_audio_processors
vendor: juce
version: 5.1.2
name: JUCE audio processor classes
description: Classes for loading and playing VST, AU, or internally-generated audio processors.
website: http://www.juce.com/juce
license: GPL/Commercial
dependencies: juce_gui_extra, juce_audio_basics
OSXFrameworks: CoreAudio CoreMIDI AudioToolbox
iOSFrameworks: AudioToolbox
END_JUCE_MODULE_DECLARATION
*******************************************************************************/
#pragma once
#define JUCE_AUDIO_PROCESSORS_H_INCLUDED
#include <juce_gui_basics/juce_gui_basics.h>
#include <juce_audio_basics/juce_audio_basics.h>
//==============================================================================
/** Config: JUCE_PLUGINHOST_VST
Enables the VST audio plugin hosting classes.
@see VSTPluginFormat, VST3PluginFormat, AudioPluginFormat, AudioPluginFormatManager, JUCE_PLUGINHOST_AU, JUCE_PLUGINHOST_VST3
*/
#ifndef JUCE_PLUGINHOST_VST
#define JUCE_PLUGINHOST_VST 0
#endif
/** Config: JUCE_PLUGINHOST_VST3
Enables the VST3 audio plugin hosting classes. This requires the Steinberg VST3 SDK to be
installed on your machine.
@see VSTPluginFormat, VST3PluginFormat, AudioPluginFormat, AudioPluginFormatManager, JUCE_PLUGINHOST_VST, JUCE_PLUGINHOST_AU
*/
#ifndef JUCE_PLUGINHOST_VST3
#define JUCE_PLUGINHOST_VST3 0
#endif
/** Config: JUCE_PLUGINHOST_AU
Enables the AudioUnit plugin hosting classes. This is Mac-only, of course.
@see AudioUnitPluginFormat, AudioPluginFormat, AudioPluginFormatManager, JUCE_PLUGINHOST_VST, JUCE_PLUGINHOST_VST3
*/
#ifndef JUCE_PLUGINHOST_AU
#define JUCE_PLUGINHOST_AU 0
#endif
#if ! (JUCE_PLUGINHOST_AU || JUCE_PLUGINHOST_VST || JUCE_PLUGINHOST_VST3)
// #error "You need to set either the JUCE_PLUGINHOST_AU and/or JUCE_PLUGINHOST_VST and/or JUCE_PLUGINHOST_VST3 flags if you're using this module!"
#endif
#if ! (defined (JUCE_SUPPORT_CARBON) || JUCE_64BIT || JUCE_IOS)
#define JUCE_SUPPORT_CARBON 1
#endif
#ifndef JUCE_SUPPORT_LEGACY_AUDIOPROCESSOR
#define JUCE_SUPPORT_LEGACY_AUDIOPROCESSOR 1
#endif
//==============================================================================
#include "processors/juce_AudioProcessorEditor.h"
#include "processors/juce_AudioProcessorListener.h"
#include "processors/juce_AudioProcessorParameter.h"
#include "processors/juce_AudioProcessor.h"
#include "processors/juce_PluginDescription.h"
#include "processors/juce_AudioPluginInstance.h"
#include "processors/juce_AudioProcessorGraph.h"
#include "processors/juce_GenericAudioProcessorEditor.h"
#include "format/juce_AudioPluginFormat.h"
#include "format/juce_AudioPluginFormatManager.h"
#include "scanning/juce_KnownPluginList.h"
#include "format_types/juce_AudioUnitPluginFormat.h"
#include "format_types/juce_LADSPAPluginFormat.h"
#include "format_types/juce_VSTMidiEventList.h"
#include "format_types/juce_VSTPluginFormat.h"
#include "format_types/juce_VST3PluginFormat.h"
#include "scanning/juce_PluginDirectoryScanner.h"
#include "scanning/juce_PluginListComponent.h"
#include "utilities/juce_AudioProcessorParameterWithID.h"
#include "utilities/juce_AudioParameterFloat.h"
#include "utilities/juce_AudioParameterInt.h"
#include "utilities/juce_AudioParameterBool.h"
#include "utilities/juce_AudioParameterChoice.h"
#include "utilities/juce_AudioProcessorValueTreeState.h"

+ 0
- 89
source/modules/juce_audio_processors/processors/juce_AudioPluginInstance.h View File

@@ -1,89 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
Base class for an active instance of a plugin.
This derives from the AudioProcessor class, and adds some extra functionality
that helps when wrapping dynamically loaded plugins.
This class is not needed when writing plugins, and you should never need to derive
your own sub-classes from it. The plugin hosting classes use it internally and will
return AudioPluginInstance objects which wrap external plugins.
@see AudioProcessor, AudioPluginFormat
*/
class JUCE_API AudioPluginInstance : public AudioProcessor
{
public:
//==============================================================================
/** Destructor.
Make sure that you delete any UI components that belong to this plugin before
deleting the plugin.
*/
virtual ~AudioPluginInstance() {}
//==============================================================================
/** Fills-in the appropriate parts of this plugin description object. */
virtual void fillInPluginDescription (PluginDescription& description) const = 0;
/** Returns a PluginDescription for this plugin.
This is just a convenience method to avoid calling fillInPluginDescription.
*/
PluginDescription getPluginDescription() const
{
PluginDescription desc;
fillInPluginDescription (desc);
return desc;
}
/** Returns a pointer to some kind of platform-specific data about the plugin.
E.g. For a VST, this value can be cast to an AEffect*. For an AudioUnit, it can be
cast to an AudioUnit handle.
*/
virtual void* getPlatformSpecificData() { return nullptr; }
/** For some formats (currently AudioUnit), this forces a reload of the list of
available parameters.
*/
virtual void refreshParameterList() {}
protected:
//==============================================================================
AudioPluginInstance() {}
AudioPluginInstance (const BusesProperties& ioLayouts) : AudioProcessor (ioLayouts) {}
template <int numLayouts>
AudioPluginInstance (const short channelLayoutList[numLayouts][2]) : AudioProcessor (channelLayoutList) {}
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioPluginInstance)
};
} // namespace juce

+ 0
- 1464
source/modules/juce_audio_processors/processors/juce_AudioProcessor.cpp
File diff suppressed because it is too large
View File


+ 0
- 1641
source/modules/juce_audio_processors/processors/juce_AudioProcessor.h
File diff suppressed because it is too large
View File


+ 0
- 189
source/modules/juce_audio_processors/processors/juce_AudioProcessorEditor.cpp View File

@@ -1,189 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
AudioProcessorEditor::AudioProcessorEditor (AudioProcessor& p) noexcept : processor (p)
{
initialise();
}
AudioProcessorEditor::AudioProcessorEditor (AudioProcessor* p) noexcept : processor (*p)
{
// the filter must be valid..
jassert (p != nullptr);
initialise();
}
AudioProcessorEditor::~AudioProcessorEditor()
{
// if this fails, then the wrapper hasn't called editorBeingDeleted() on the
// filter for some reason..
jassert (processor.getActiveEditor() != this);
removeComponentListener (resizeListener);
}
void AudioProcessorEditor::setControlHighlight (ParameterControlHighlightInfo) {}
int AudioProcessorEditor::getControlParameterIndex (Component&) { return -1; }
bool AudioProcessorEditor::supportsHostMIDIControllerPresence (bool) { return true; }
void AudioProcessorEditor::hostMIDIControllerIsAvailable (bool) {}
void AudioProcessorEditor::initialise()
{
resizable = false;
attachConstrainer (&defaultConstrainer);
addComponentListener (resizeListener = new AudioProcessorEditorListener (*this));
}
//==============================================================================
void AudioProcessorEditor::setResizable (const bool shouldBeResizable, const bool useBottomRightCornerResizer)
{
if (shouldBeResizable != resizable)
{
resizable = shouldBeResizable;
if (! resizable)
{
setConstrainer (&defaultConstrainer);
if (auto w = getWidth())
{
if (auto h = getHeight())
{
defaultConstrainer.setSizeLimits (w, h, w, h);
resized();
}
}
}
}
bool shouldHaveCornerResizer = (useBottomRightCornerResizer && shouldBeResizable);
if (shouldHaveCornerResizer != (resizableCorner != nullptr))
{
if (shouldHaveCornerResizer)
{
Component::addChildComponent (resizableCorner = new ResizableCornerComponent (this, constrainer));
resizableCorner->setAlwaysOnTop (true);
}
else
{
resizableCorner = nullptr;
}
}
}
void AudioProcessorEditor::setResizeLimits (int newMinimumWidth,
int newMinimumHeight,
int newMaximumWidth,
int newMaximumHeight) noexcept
{
// if you've set up a custom constrainer then these settings won't have any effect..
jassert (constrainer == &defaultConstrainer || constrainer == nullptr);
const bool shouldEnableResize = (newMinimumWidth != newMaximumWidth || newMinimumHeight != newMaximumHeight);
const bool shouldHaveCornerResizer = (shouldEnableResize != resizable || resizableCorner != nullptr);
setResizable (shouldEnableResize, shouldHaveCornerResizer);
if (constrainer == nullptr)
setConstrainer (&defaultConstrainer);
defaultConstrainer.setSizeLimits (newMinimumWidth, newMinimumHeight,
newMaximumWidth, newMaximumHeight);
setBoundsConstrained (getBounds());
}
void AudioProcessorEditor::setConstrainer (ComponentBoundsConstrainer* newConstrainer)
{
if (constrainer != newConstrainer)
{
resizable = true;
attachConstrainer (newConstrainer);
}
}
void AudioProcessorEditor::attachConstrainer (ComponentBoundsConstrainer* newConstrainer)
{
if (constrainer != newConstrainer)
{
constrainer = newConstrainer;
updatePeer();
}
}
void AudioProcessorEditor::setBoundsConstrained (Rectangle<int> newBounds)
{
if (constrainer != nullptr)
constrainer->setBoundsForComponent (this, newBounds, false, false, false, false);
else
setBounds (newBounds);
}
void AudioProcessorEditor::editorResized (bool wasResized)
{
if (wasResized)
{
bool resizerHidden = false;
if (auto* peer = getPeer())
resizerHidden = peer->isFullScreen() || peer->isKioskMode();
if (resizableCorner != nullptr)
{
resizableCorner->setVisible (! resizerHidden);
const int resizerSize = 18;
resizableCorner->setBounds (getWidth() - resizerSize,
getHeight() - resizerSize,
resizerSize, resizerSize);
}
if (! resizable)
if (auto w = getWidth())
if (auto h = getHeight())
defaultConstrainer.setSizeLimits (w, h, w, h);
}
}
void AudioProcessorEditor::updatePeer()
{
if (isOnDesktop())
if (auto* peer = getPeer())
peer->setConstrainer (constrainer);
}
void AudioProcessorEditor::setScaleFactor (float newScale)
{
setTransform (AffineTransform::scale (newScale));
editorResized (true);
}
} // namespace juce

+ 0
- 209
source/modules/juce_audio_processors/processors/juce_AudioProcessorEditor.h View File

@@ -1,209 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
class AudioProcessor;
class AudioProcessorEditorListener;
//==============================================================================
/**
Base class for the component that acts as the GUI for an AudioProcessor.
Derive your editor component from this class, and create an instance of it
by overriding the AudioProcessor::createEditor() method.
@see AudioProcessor, GenericAudioProcessorEditor
*/
class JUCE_API AudioProcessorEditor : public Component
{
protected:
//==============================================================================
/** Creates an editor for the specified processor. */
AudioProcessorEditor (AudioProcessor&) noexcept;
/** Creates an editor for the specified processor. */
AudioProcessorEditor (AudioProcessor*) noexcept;
public:
/** Destructor. */
~AudioProcessorEditor();
//==============================================================================
/** The AudioProcessor that this editor represents. */
AudioProcessor& processor;
/** Returns a pointer to the processor that this editor represents.
This method is here to support legacy code, but it's easier to just use the
AudioProcessorEditor::processor member variable directly to get this object.
*/
AudioProcessor* getAudioProcessor() const noexcept { return &processor; }
//==============================================================================
/** Used by the setParameterHighlighting() method. */
struct ParameterControlHighlightInfo
{
int parameterIndex;
bool isHighlighted;
Colour suggestedColour;
};
/** Some types of plugin can call this to suggest that the control for a particular
parameter should be highlighted.
Currently only AAX plugins will call this, and implementing it is optional.
*/
virtual void setControlHighlight (ParameterControlHighlightInfo);
/** Called by certain plug-in wrappers to find out whether a component is used
to control a parameter.
If the given component represents a particular plugin parameter, then this
method should return the index of that parameter. If not, it should return -1.
Currently only AAX plugins will call this, and implementing it is optional.
*/
virtual int getControlParameterIndex (Component&);
/** Override this method to indicate if your editor supports the presence or
absence of a host-provided MIDI controller.
Currently only AUv3 plug-ins compiled for MacOS 10.13 or iOS 11.0 (or later)
support this functionality, and even then the host may choose to ignore this
information.
The default behaviour is to report support for both cases.
*/
virtual bool supportsHostMIDIControllerPresence (bool hostMIDIControllerIsAvailable);
/** Called to indicate if a host is providing a MIDI controller when the host
reconfigures its layout.
Use this as an opportunity to hide or display your own onscreen keyboard or
other input component.
Currently only AUv3 plug-ins compiled for MacOS 10.13 or iOS 11.0 (or later)
support this functionality.
*/
virtual void hostMIDIControllerIsAvailable (bool controllerIsAvailable);
/** Can be called by a host to tell the editor that it should use a non-unity
GUI scale.
*/
virtual void setScaleFactor (float newScale);
//==============================================================================
/** Marks the host's editor window as resizable
@param allowHostToResize whether the editor's parent window can be resized
by the user or the host. Even if this is false, you
can still resize your window yourself by calling
setBounds (for example, when a user clicks on a button
in your editor to drop out a panel) which will bypass any
resizable/constraints checks. If you are using
your own corner resizer than this will also bypass
any checks.
@param useBottomRightCornerResizer
@see setResizeLimits, isResizable
*/
void setResizable (bool allowHostToResize, bool useBottomRightCornerResizer);
/** Returns true if the host is allowed to resize editor's parent window
@see setResizable
*/
bool isResizable() const noexcept { return resizable; }
/** This sets the maximum and minimum sizes for the window.
If the window's current size is outside these limits, it will be resized to
make sure it's within them.
A direct call to setBounds() will bypass any constraint checks, but when the
window is dragged by the user or resized by other indirect means, the constrainer
will limit the numbers involved.
@see setResizable
*/
void setResizeLimits (int newMinimumWidth,
int newMinimumHeight,
int newMaximumWidth,
int newMaximumHeight) noexcept;
/** Returns the bounds constrainer object that this window is using.
You can access this to change its properties.
*/
ComponentBoundsConstrainer* getConstrainer() noexcept { return constrainer; }
/** Sets the bounds-constrainer object to use for resizing and dragging this window.
A pointer to the object you pass in will be kept, but it won't be deleted
by this object, so it's the caller's responsibility to manage it.
If you pass a nullptr, then no contraints will be placed on the positioning of the window.
*/
void setConstrainer (ComponentBoundsConstrainer* newConstrainer);
/** Calls the window's setBounds method, after first checking these bounds
with the current constrainer.
@see setConstrainer
*/
void setBoundsConstrained (Rectangle<int> newBounds);
ScopedPointer<ResizableCornerComponent> resizableCorner;
private:
//==============================================================================
struct AudioProcessorEditorListener : ComponentListener
{
AudioProcessorEditorListener (AudioProcessorEditor& e) : ed (e) {}
void componentMovedOrResized (Component&, bool, bool wasResized) override { ed.editorResized (wasResized); }
void componentParentHierarchyChanged (Component&) override { ed.updatePeer(); }
AudioProcessorEditor& ed;
JUCE_DECLARE_NON_COPYABLE (AudioProcessorEditorListener)
};
//==============================================================================
void initialise();
void editorResized (bool wasResized);
void updatePeer();
void attachConstrainer (ComponentBoundsConstrainer*);
//==============================================================================
ScopedPointer<AudioProcessorEditorListener> resizeListener;
bool resizable;
ComponentBoundsConstrainer defaultConstrainer;
ComponentBoundsConstrainer* constrainer = {};
JUCE_DECLARE_NON_COPYABLE (AudioProcessorEditor)
};
} // namespace juce

+ 0
- 1702
source/modules/juce_audio_processors/processors/juce_AudioProcessorGraph.cpp
File diff suppressed because it is too large
View File


+ 0
- 411
source/modules/juce_audio_processors/processors/juce_AudioProcessorGraph.h View File

@@ -1,411 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
A type of AudioProcessor which plays back a graph of other AudioProcessors.
Use one of these objects if you want to wire-up a set of AudioProcessors
and play back the result.
Processors can be added to the graph as "nodes" using addNode(), and once
added, you can connect any of their input or output channels to other
nodes using addConnection().
To play back a graph through an audio device, you might want to use an
AudioProcessorPlayer object.
*/
class JUCE_API AudioProcessorGraph : public AudioProcessor,
private AsyncUpdater
{
public:
//==============================================================================
/** Creates an empty graph. */
AudioProcessorGraph();
/** Destructor.
Any processor objects that have been added to the graph will also be deleted.
*/
~AudioProcessorGraph();
//==============================================================================
/** Represents one of the nodes, or processors, in an AudioProcessorGraph.
To create a node, call AudioProcessorGraph::addNode().
*/
class JUCE_API Node : public ReferenceCountedObject
{
public:
//==============================================================================
/** The ID number assigned to this node.
This is assigned by the graph that owns it, and can't be changed.
*/
const uint32 nodeId;
/** The actual processor object that this node represents. */
AudioProcessor* getProcessor() const noexcept { return processor; }
/** A set of user-definable properties that are associated with this node.
This can be used to attach values to the node for whatever purpose seems
useful. For example, you might store an x and y position if your application
is displaying the nodes on-screen.
*/
NamedValueSet properties;
//==============================================================================
/** A convenient typedef for referring to a pointer to a node object. */
typedef ReferenceCountedObjectPtr<Node> Ptr;
private:
//==============================================================================
friend class AudioProcessorGraph;
const ScopedPointer<AudioProcessor> processor;
bool isPrepared;
Node (uint32 nodeId, AudioProcessor*) noexcept;
void setParentGraph (AudioProcessorGraph*) const;
void prepare (double newSampleRate, int newBlockSize, AudioProcessorGraph*, ProcessingPrecision);
void unprepare();
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Node)
};
//==============================================================================
/** Represents a connection between two channels of two nodes in an AudioProcessorGraph.
To create a connection, use AudioProcessorGraph::addConnection().
*/
struct JUCE_API Connection
{
//==============================================================================
Connection (uint32 sourceNodeId, int sourceChannelIndex,
uint32 destNodeId, int destChannelIndex) noexcept;
//==============================================================================
/** The ID number of the node which is the input source for this connection.
@see AudioProcessorGraph::getNodeForId
*/
uint32 sourceNodeId;
/** The index of the output channel of the source node from which this
connection takes its data.
If this value is the special number AudioProcessorGraph::midiChannelIndex, then
it is referring to the source node's midi output. Otherwise, it is the zero-based
index of an audio output channel in the source node.
*/
int sourceChannelIndex;
/** The ID number of the node which is the destination for this connection.
@see AudioProcessorGraph::getNodeForId
*/
uint32 destNodeId;
/** The index of the input channel of the destination node to which this
connection delivers its data.
If this value is the special number AudioProcessorGraph::midiChannelIndex, then
it is referring to the destination node's midi input. Otherwise, it is the zero-based
index of an audio input channel in the destination node.
*/
int destChannelIndex;
private:
//==============================================================================
JUCE_LEAK_DETECTOR (Connection)
};
//==============================================================================
/** Deletes all nodes and connections from this graph.
Any processor objects in the graph will be deleted.
*/
void clear();
/** Returns the number of nodes in the graph. */
int getNumNodes() const noexcept { return nodes.size(); }
/** Returns a pointer to one of the nodes in the graph.
This will return nullptr if the index is out of range.
@see getNodeForId
*/
Node* getNode (const int index) const noexcept { return nodes [index]; }
/** Searches the graph for a node with the given ID number and returns it.
If no such node was found, this returns nullptr.
@see getNode
*/
Node* getNodeForId (const uint32 nodeId) const;
/** Adds a node to the graph.
This creates a new node in the graph, for the specified processor. Once you have
added a processor to the graph, the graph owns it and will delete it later when
it is no longer needed.
The optional nodeId parameter lets you specify an ID to use for the node, but
if the value is already in use, this new node will overwrite the old one.
If this succeeds, it returns a pointer to the newly-created node.
*/
Node* addNode (AudioProcessor* newProcessor, uint32 nodeId = 0);
/** Deletes a node within the graph which has the specified ID.
This will also delete any connections that are attached to this node.
*/
bool removeNode (uint32 nodeId);
/** Deletes a node within the graph.
This will also delete any connections that are attached to this node.
*/
bool removeNode (Node* node);
//==============================================================================
/** Returns the number of connections in the graph. */
int getNumConnections() const { return connections.size(); }
/** Returns a pointer to one of the connections in the graph. */
const Connection* getConnection (int index) const { return connections [index]; }
/** Searches for a connection between some specified channels.
If no such connection is found, this returns nullptr.
*/
const Connection* getConnectionBetween (uint32 sourceNodeId,
int sourceChannelIndex,
uint32 destNodeId,
int destChannelIndex) const;
/** Returns true if there is a connection between any of the channels of
two specified nodes.
*/
bool isConnected (uint32 possibleSourceNodeId,
uint32 possibleDestNodeId) const;
/** Returns true if it would be legal to connect the specified points. */
bool canConnect (uint32 sourceNodeId, int sourceChannelIndex,
uint32 destNodeId, int destChannelIndex) const;
/** Attempts to connect two specified channels of two nodes.
If this isn't allowed (e.g. because you're trying to connect a midi channel
to an audio one or other such nonsense), then it'll return false.
*/
bool addConnection (uint32 sourceNodeId, int sourceChannelIndex,
uint32 destNodeId, int destChannelIndex);
/** Deletes the connection with the specified index. */
void removeConnection (int index);
/** Deletes any connection between two specified points.
Returns true if a connection was actually deleted.
*/
bool removeConnection (uint32 sourceNodeId, int sourceChannelIndex,
uint32 destNodeId, int destChannelIndex);
/** Removes all connections from the specified node. */
bool disconnectNode (uint32 nodeId);
/** Returns true if the given connection's channel numbers map on to valid
channels at each end.
Even if a connection is valid when created, its status could change if
a node changes its channel config.
*/
bool isConnectionLegal (const Connection* connection) const;
/** Performs a sanity checks of all the connections.
This might be useful if some of the processors are doing things like changing
their channel counts, which could render some connections obsolete.
*/
bool removeIllegalConnections();
//==============================================================================
/** A special number that represents the midi channel of a node.
This is used as a channel index value if you want to refer to the midi input
or output instead of an audio channel.
*/
static const int midiChannelIndex;
//==============================================================================
/** A special type of AudioProcessor that can live inside an AudioProcessorGraph
in order to use the audio that comes into and out of the graph itself.
If you create an AudioGraphIOProcessor in "input" mode, it will act as a
node in the graph which delivers the audio that is coming into the parent
graph. This allows you to stream the data to other nodes and process the
incoming audio.
Likewise, one of these in "output" mode can be sent data which it will add to
the sum of data being sent to the graph's output.
@see AudioProcessorGraph
*/
class JUCE_API AudioGraphIOProcessor : public AudioPluginInstance
{
public:
/** Specifies the mode in which this processor will operate.
*/
enum IODeviceType
{
audioInputNode, /**< In this mode, the processor has output channels
representing all the audio input channels that are
coming into its parent audio graph. */
audioOutputNode, /**< In this mode, the processor has input channels
representing all the audio output channels that are
going out of its parent audio graph. */
midiInputNode, /**< In this mode, the processor has a midi output which
delivers the same midi data that is arriving at its
parent graph. */
midiOutputNode /**< In this mode, the processor has a midi input and
any data sent to it will be passed out of the parent
graph. */
};
//==============================================================================
/** Returns the mode of this processor. */
IODeviceType getType() const noexcept { return type; }
/** Returns the parent graph to which this processor belongs, or nullptr if it
hasn't yet been added to one. */
AudioProcessorGraph* getParentGraph() const noexcept { return graph; }
/** True if this is an audio or midi input. */
bool isInput() const noexcept;
/** True if this is an audio or midi output. */
bool isOutput() const noexcept;
//==============================================================================
AudioGraphIOProcessor (const IODeviceType type);
~AudioGraphIOProcessor();
const String getName() const override;
void fillInPluginDescription (PluginDescription&) const override;
void prepareToPlay (double newSampleRate, int estimatedSamplesPerBlock) override;
void releaseResources() override;
void processBlock (AudioBuffer<float>& , MidiBuffer&) override;
void processBlock (AudioBuffer<double>&, MidiBuffer&) override;
bool supportsDoublePrecisionProcessing() const override;
double getTailLengthSeconds() const override;
bool acceptsMidi() const override;
bool producesMidi() const override;
#if ! JUCE_AUDIOPROCESSOR_NO_GUI
bool hasEditor() const override;
AudioProcessorEditor* createEditor() override;
#endif
int getNumPrograms() override;
int getCurrentProgram() override;
void setCurrentProgram (int) override;
const String getProgramName (int) override;
void changeProgramName (int, const String&) override;
void getStateInformation (juce::MemoryBlock& destData) override;
void setStateInformation (const void* data, int sizeInBytes) override;
/** @internal */
void setParentGraph (AudioProcessorGraph*);
private:
const IODeviceType type;
AudioProcessorGraph* graph;
//==============================================================================
template <typename floatType>
void processAudio (AudioBuffer<floatType>& buffer, MidiBuffer& midiMessages);
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioGraphIOProcessor)
};
//==============================================================================
const String getName() const override;
void prepareToPlay (double, int) override;
void releaseResources() override;
void processBlock (AudioBuffer<float>&, MidiBuffer&) override;
void processBlock (AudioBuffer<double>&, MidiBuffer&) override;
bool supportsDoublePrecisionProcessing() const override;
void reset() override;
void setNonRealtime (bool) noexcept override;
void setPlayHead (AudioPlayHead*) override;
double getTailLengthSeconds() const override;
bool acceptsMidi() const override;
bool producesMidi() const override;
#if ! JUCE_AUDIOPROCESSOR_NO_GUI
bool hasEditor() const override { return false; }
AudioProcessorEditor* createEditor() override { return nullptr; }
#endif
int getNumPrograms() override { return 0; }
int getCurrentProgram() override { return 0; }
void setCurrentProgram (int) override { }
const String getProgramName (int) override { return {}; }
void changeProgramName (int, const String&) override { }
void getStateInformation (juce::MemoryBlock&) override;
void setStateInformation (const void* data, int sizeInBytes) override;
private:
//==============================================================================
template <typename floatType>
void processAudio (AudioBuffer<floatType>& buffer, MidiBuffer& midiMessages);
template <typename floatType>
void sliceAndProcess (AudioBuffer<floatType>& buffer, MidiBuffer& midiMessages);
//==============================================================================
ReferenceCountedArray<Node> nodes;
OwnedArray<Connection> connections;
uint32 lastNodeId;
OwnedArray<MidiBuffer> midiBuffers;
Array<void*> renderingOps;
friend class AudioGraphIOProcessor;
struct AudioProcessorGraphBufferHelpers;
ScopedPointer<AudioProcessorGraphBufferHelpers> audioBuffers;
MidiBuffer* currentMidiInputBuffer;
MidiBuffer currentMidiOutputBuffer;
bool isPrepared;
void handleAsyncUpdate() override;
void clearRenderingSequence();
void buildRenderingSequence();
bool isAnInputTo (uint32 possibleInputId, uint32 possibleDestinationId, int recursionCheck) const;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioProcessorGraph)
};
} // namespace juce

+ 0
- 107
source/modules/juce_audio_processors/processors/juce_AudioProcessorListener.h View File

@@ -1,107 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
Base class for listeners that want to know about changes to an AudioProcessor.
Use AudioProcessor::addListener() to register your listener with an AudioProcessor.
@see AudioProcessor
*/
class JUCE_API AudioProcessorListener
{
public:
//==============================================================================
/** Destructor. */
virtual ~AudioProcessorListener() {}
//==============================================================================
/** Receives a callback when a parameter is changed.
IMPORTANT NOTE: this will be called synchronously when a parameter changes, and
many audio processors will change their parameter during their audio callback.
This means that not only has your handler code got to be completely thread-safe,
but it's also got to be VERY fast, and avoid blocking. If you need to handle
this event on your message thread, use this callback to trigger an AsyncUpdater
or ChangeBroadcaster which you can respond to on the message thread.
*/
virtual void audioProcessorParameterChanged (AudioProcessor* processor,
int parameterIndex,
float newValue) = 0;
/** Called to indicate that something else in the plugin has changed, like its
program, number of parameters, etc.
IMPORTANT NOTE: this will be called synchronously, and many audio processors will
call it during their audio callback. This means that not only has your handler code
got to be completely thread-safe, but it's also got to be VERY fast, and avoid
blocking. If you need to handle this event on your message thread, use this callback
to trigger an AsyncUpdater or ChangeBroadcaster which you can respond to later on the
message thread.
*/
virtual void audioProcessorChanged (AudioProcessor* processor) = 0;
/** Indicates that a parameter change gesture has started.
E.g. if the user is dragging a slider, this would be called when they first
press the mouse button, and audioProcessorParameterChangeGestureEnd would be
called when they release it.
IMPORTANT NOTE: this will be called synchronously, and many audio processors will
call it during their audio callback. This means that not only has your handler code
got to be completely thread-safe, but it's also got to be VERY fast, and avoid
blocking. If you need to handle this event on your message thread, use this callback
to trigger an AsyncUpdater or ChangeBroadcaster which you can respond to later on the
message thread.
@see audioProcessorParameterChangeGestureEnd
*/
virtual void audioProcessorParameterChangeGestureBegin (AudioProcessor* processor,
int parameterIndex);
/** Indicates that a parameter change gesture has finished.
E.g. if the user is dragging a slider, this would be called when they release
the mouse button.
IMPORTANT NOTE: this will be called synchronously, and many audio processors will
call it during their audio callback. This means that not only has your handler code
got to be completely thread-safe, but it's also got to be VERY fast, and avoid
blocking. If you need to handle this event on your message thread, use this callback
to trigger an AsyncUpdater or ChangeBroadcaster which you can respond to later on the
message thread.
@see audioProcessorParameterChangeGestureBegin
*/
virtual void audioProcessorParameterChangeGestureEnd (AudioProcessor* processor,
int parameterIndex);
};
} // namespace juce

+ 0
- 197
source/modules/juce_audio_processors/processors/juce_AudioProcessorParameter.h View File

@@ -1,197 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/** An abstract base class for parameter objects that can be added to an
AudioProcessor.
@see AudioProcessor::addParameter
*/
class JUCE_API AudioProcessorParameter
{
public:
AudioProcessorParameter() noexcept;
/** Destructor. */
virtual ~AudioProcessorParameter();
/** Called by the host to find out the value of this parameter.
Hosts will expect the value returned to be between 0 and 1.0.
This could be called quite frequently, so try to make your code efficient.
It's also likely to be called by non-UI threads, so the code in here should
be thread-aware.
*/
virtual float getValue() const = 0;
/** The host will call this method to change the value of one of the filter's parameters.
The host may call this at any time, including during the audio processing
callback, so the filter has to process this very fast and avoid blocking.
If you want to set the value of a parameter internally, e.g. from your
editor component, then don't call this directly - instead, use the
setValueNotifyingHost() method, which will also send a message to
the host telling it about the change. If the message isn't sent, the host
won't be able to automate your parameters properly.
The value passed will be between 0 and 1.0.
*/
virtual void setValue (float newValue) = 0;
/** Your filter can call this when it needs to change one of its parameters.
This could happen when the editor or some other internal operation changes
a parameter. This method will call the setValue() method to change the
value, and will then send a message to the host telling it about the change.
Note that to make sure the host correctly handles automation, you should call
the beginChangeGesture() and endChangeGesture() methods to tell the host when
the user has started and stopped changing the parameter.
*/
void setValueNotifyingHost (float newValue);
/** Sends a signal to the host to tell it that the user is about to start changing this
parameter.
This allows the host to know when a parameter is actively being held by the user, and
it may use this information to help it record automation.
If you call this, it must be matched by a later call to endChangeGesture().
*/
void beginChangeGesture();
/** Tells the host that the user has finished changing this parameter.
This allows the host to know when a parameter is actively being held by the user,
and it may use this information to help it record automation.
A call to this method must follow a call to beginChangeGesture().
*/
void endChangeGesture();
/** This should return the default value for this parameter. */
virtual float getDefaultValue() const = 0;
/** Returns the name to display for this parameter, which should be made
to fit within the given string length.
*/
virtual String getName (int maximumStringLength) const = 0;
/** Some parameters may be able to return a label string for
their units. For example "Hz" or "%".
*/
virtual String getLabel() const = 0;
/** Returns the number of steps that this parameter's range should be quantised into.
If you want a continuous range of values, don't override this method, and allow
the default implementation to return AudioProcessor::getDefaultNumParameterSteps().
If your parameter is boolean, then you may want to make this return 2.
The value that is returned may or may not be used, depending on the host. If you
want the host to display stepped automation values, rather than a continuous
interpolation between successive values, you should override isDiscrete to return true.
@see isDiscrete
*/
virtual int getNumSteps() const;
/** Returns whether the parameter uses discrete values, based on the result of
getNumSteps, or allows the host to select values continuously.
This information may or may not be used, depending on the host. If you
want the host to display stepped automation values, rather than a continuous
interpolation between successive values, override this method to return true.
@see getNumSteps
*/
virtual bool isDiscrete() const;
/** Returns a textual version of the supplied parameter value.
The default implementation just returns the floating point value
as a string, but this could do anything you need for a custom type
of value.
*/
virtual String getText (float value, int /*maximumStringLength*/) const;
/** Should parse a string and return the appropriate value for it. */
virtual float getValueForText (const String& text) const = 0;
/** This can be overridden to tell the host that this parameter operates in the
reverse direction.
(Not all plugin formats or hosts will actually use this information).
*/
virtual bool isOrientationInverted() const;
/** Returns true if the host can automate this parameter.
By default, this returns true.
*/
virtual bool isAutomatable() const;
/** Should return true if this parameter is a "meta" parameter.
A meta-parameter is a parameter that changes other params. It is used
by some hosts (e.g. AudioUnit hosts).
By default this returns false.
*/
virtual bool isMetaParameter() const;
enum Category
{
genericParameter = (0 << 16) | 0, /** If your parameter is not a meter then you should use this category */
inputGain = (1 << 16) | 0, /** Currently not used */
outputGain = (1 << 16) | 1,
/** The following categories tell the host that this parameter is a meter level value
and therefore read-only. Most hosts will display these type of parameters as
a meter in the generic view of your plug-in. Pro-Tools will also show the meter
in the mixer view.
*/
inputMeter = (2 << 16) | 0,
outputMeter = (2 << 16) | 1,
compressorLimiterGainReductionMeter = (2 << 16) | 2,
expanderGateGainReductionMeter = (2 << 16) | 3,
analysisMeter = (2 << 16) | 4,
otherMeter = (2 << 16) | 5
};
/** Returns the parameter's category. */
virtual Category getCategory() const;
/** Returns the index of this parameter in its parent processor's parameter list. */
int getParameterIndex() const noexcept { return parameterIndex; }
private:
friend class AudioProcessor;
AudioProcessor* processor;
int parameterIndex;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioProcessorParameter)
};
} // namespace juce

+ 0
- 192
source/modules/juce_audio_processors/processors/juce_GenericAudioProcessorEditor.cpp View File

@@ -1,192 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
class ProcessorParameterPropertyComp : public PropertyComponent,
private AudioProcessorListener,
private Timer
{
public:
ProcessorParameterPropertyComp (const String& name, AudioProcessor& p, int paramIndex)
: PropertyComponent (name),
owner (p),
index (paramIndex),
paramHasChanged (false),
slider (p, paramIndex)
{
startTimer (100);
addAndMakeVisible (slider);
owner.addListener (this);
}
~ProcessorParameterPropertyComp()
{
owner.removeListener (this);
}
void refresh() override
{
paramHasChanged = false;
if (slider.getThumbBeingDragged() < 0)
slider.setValue (owner.getParameter (index), dontSendNotification);
slider.updateText();
}
void audioProcessorChanged (AudioProcessor*) override {}
void audioProcessorParameterChanged (AudioProcessor*, int parameterIndex, float) override
{
if (parameterIndex == index)
paramHasChanged = true;
}
void timerCallback() override
{
if (paramHasChanged)
{
refresh();
startTimerHz (50);
}
else
{
startTimer (jmin (1000 / 4, getTimerInterval() + 10));
}
}
private:
//==============================================================================
class ParamSlider : public Slider
{
public:
ParamSlider (AudioProcessor& p, int paramIndex) : owner (p), index (paramIndex)
{
const int steps = owner.getParameterNumSteps (index);
const AudioProcessorParameter::Category category = p.getParameterCategory (index);
const bool isLevelMeter = (((category & 0xffff0000) >> 16) == 2);
if (steps > 1 && steps < 0x7fffffff)
setRange (0.0, 1.0, 1.0 / (steps - 1.0));
else
setRange (0.0, 1.0);
setEnabled (! isLevelMeter);
setSliderStyle (Slider::LinearBar);
setTextBoxIsEditable (false);
setScrollWheelEnabled (true);
}
void valueChanged() override
{
const float newVal = (float) getValue();
if (owner.getParameter (index) != newVal)
{
owner.setParameterNotifyingHost (index, newVal);
updateText();
}
}
void startedDragging() override
{
owner.beginParameterChangeGesture(index);
}
void stoppedDragging() override
{
owner.endParameterChangeGesture(index);
}
String getTextFromValue (double /*value*/) override
{
return owner.getParameterText (index) + " " + owner.getParameterLabel (index).trimEnd();
}
private:
//==============================================================================
AudioProcessor& owner;
const int index;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ParamSlider)
};
AudioProcessor& owner;
const int index;
bool volatile paramHasChanged;
ParamSlider slider;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ProcessorParameterPropertyComp)
};
//==============================================================================
GenericAudioProcessorEditor::GenericAudioProcessorEditor (AudioProcessor* const p)
: AudioProcessorEditor (p)
{
jassert (p != nullptr);
setOpaque (true);
addAndMakeVisible (panel);
Array <PropertyComponent*> params;
const int numParams = p->getNumParameters();
int totalHeight = 0;
for (int i = 0; i < numParams; ++i)
{
String name (p->getParameterName (i));
if (name.trim().isEmpty())
name = "Unnamed";
ProcessorParameterPropertyComp* const pc = new ProcessorParameterPropertyComp (name, *p, i);
params.add (pc);
totalHeight += pc->getPreferredHeight();
}
panel.addProperties (params);
setSize (400, jlimit (25, 400, totalHeight));
}
GenericAudioProcessorEditor::~GenericAudioProcessorEditor()
{
}
void GenericAudioProcessorEditor::paint (Graphics& g)
{
g.fillAll (Colours::white);
}
void GenericAudioProcessorEditor::resized()
{
panel.setBounds (getLocalBounds());
}
} // namespace juce

+ 0
- 58
source/modules/juce_audio_processors/processors/juce_GenericAudioProcessorEditor.h View File

@@ -1,58 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
A type of UI component that displays the parameters of an AudioProcessor as
a simple list of sliders.
This can be used for showing an editor for a processor that doesn't supply
its own custom editor.
@see AudioProcessor
*/
class JUCE_API GenericAudioProcessorEditor : public AudioProcessorEditor
{
public:
//==============================================================================
GenericAudioProcessorEditor (AudioProcessor* owner);
~GenericAudioProcessorEditor();
//==============================================================================
void paint (Graphics&) override;
void resized() override;
private:
//==============================================================================
PropertyPanel panel;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (GenericAudioProcessorEditor)
};
} // namespace juce

+ 0
- 151
source/modules/juce_audio_processors/processors/juce_PluginDescription.cpp View File

@@ -1,151 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
PluginDescription::PluginDescription()
: uid (0),
isInstrument (false),
numInputChannels (0),
numOutputChannels (0),
hasSharedContainer (false)
{
}
PluginDescription::~PluginDescription()
{
}
PluginDescription::PluginDescription (const PluginDescription& other)
: name (other.name),
descriptiveName (other.descriptiveName),
pluginFormatName (other.pluginFormatName),
category (other.category),
manufacturerName (other.manufacturerName),
version (other.version),
fileOrIdentifier (other.fileOrIdentifier),
lastFileModTime (other.lastFileModTime),
lastInfoUpdateTime (other.lastInfoUpdateTime),
uid (other.uid),
isInstrument (other.isInstrument),
numInputChannels (other.numInputChannels),
numOutputChannels (other.numOutputChannels),
hasSharedContainer (other.hasSharedContainer)
{
}
PluginDescription& PluginDescription::operator= (const PluginDescription& other)
{
name = other.name;
descriptiveName = other.descriptiveName;
pluginFormatName = other.pluginFormatName;
category = other.category;
manufacturerName = other.manufacturerName;
version = other.version;
fileOrIdentifier = other.fileOrIdentifier;
uid = other.uid;
isInstrument = other.isInstrument;
lastFileModTime = other.lastFileModTime;
lastInfoUpdateTime = other.lastInfoUpdateTime;
numInputChannels = other.numInputChannels;
numOutputChannels = other.numOutputChannels;
hasSharedContainer = other.hasSharedContainer;
return *this;
}
bool PluginDescription::isDuplicateOf (const PluginDescription& other) const noexcept
{
return fileOrIdentifier == other.fileOrIdentifier
&& uid == other.uid;
}
static String getPluginDescSuffix (const PluginDescription& d)
{
return "-" + String::toHexString (d.fileOrIdentifier.hashCode())
+ "-" + String::toHexString (d.uid);
}
bool PluginDescription::matchesIdentifierString (const String& identifierString) const
{
return identifierString.endsWithIgnoreCase (getPluginDescSuffix (*this));
}
String PluginDescription::createIdentifierString() const
{
return pluginFormatName + "-" + name + getPluginDescSuffix (*this);
}
XmlElement* PluginDescription::createXml() const
{
XmlElement* const e = new XmlElement ("PLUGIN");
e->setAttribute ("name", name);
if (descriptiveName != name)
e->setAttribute ("descriptiveName", descriptiveName);
e->setAttribute ("format", pluginFormatName);
e->setAttribute ("category", category);
e->setAttribute ("manufacturer", manufacturerName);
e->setAttribute ("version", version);
e->setAttribute ("file", fileOrIdentifier);
e->setAttribute ("uid", String::toHexString (uid));
e->setAttribute ("isInstrument", isInstrument);
e->setAttribute ("fileTime", String::toHexString (lastFileModTime.toMilliseconds()));
e->setAttribute ("infoUpdateTime", String::toHexString (lastInfoUpdateTime.toMilliseconds()));
e->setAttribute ("numInputs", numInputChannels);
e->setAttribute ("numOutputs", numOutputChannels);
e->setAttribute ("isShell", hasSharedContainer);
return e;
}
bool PluginDescription::loadFromXml (const XmlElement& xml)
{
if (xml.hasTagName ("PLUGIN"))
{
name = xml.getStringAttribute ("name");
descriptiveName = xml.getStringAttribute ("descriptiveName", name);
pluginFormatName = xml.getStringAttribute ("format");
category = xml.getStringAttribute ("category");
manufacturerName = xml.getStringAttribute ("manufacturer");
version = xml.getStringAttribute ("version");
fileOrIdentifier = xml.getStringAttribute ("file");
uid = xml.getStringAttribute ("uid").getHexValue32();
isInstrument = xml.getBoolAttribute ("isInstrument", false);
lastFileModTime = Time (xml.getStringAttribute ("fileTime").getHexValue64());
lastInfoUpdateTime = Time (xml.getStringAttribute ("infoUpdateTime").getHexValue64());
numInputChannels = xml.getIntAttribute ("numInputs");
numOutputChannels = xml.getIntAttribute ("numOutputs");
hasSharedContainer = xml.getBoolAttribute ("isShell", false);
return true;
}
return false;
}
} // namespace juce

+ 0
- 156
source/modules/juce_audio_processors/processors/juce_PluginDescription.h View File

@@ -1,156 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
A small class to represent some facts about a particular type of plug-in.
This class is for storing and managing the details about a plug-in without
actually having to load an instance of it.
A KnownPluginList contains a list of PluginDescription objects.
@see KnownPluginList
*/
class JUCE_API PluginDescription
{
public:
//==============================================================================
PluginDescription();
PluginDescription (const PluginDescription& other);
PluginDescription& operator= (const PluginDescription& other);
~PluginDescription();
//==============================================================================
/** The name of the plug-in. */
String name;
/** A more descriptive name for the plug-in.
This may be the same as the 'name' field, but some plug-ins may provide an
alternative name.
*/
String descriptiveName;
/** The plug-in format, e.g. "VST", "AudioUnit", etc. */
String pluginFormatName;
/** A category, such as "Dynamics", "Reverbs", etc. */
String category;
/** The manufacturer. */
String manufacturerName;
/** The version. This string doesn't have any particular format. */
String version;
/** Either the file containing the plug-in module, or some other unique way
of identifying it.
E.g. for an AU, this would be an ID string that the component manager
could use to retrieve the plug-in. For a VST, it's the file path.
*/
String fileOrIdentifier;
/** The last time the plug-in file was changed.
This is handy when scanning for new or changed plug-ins.
*/
Time lastFileModTime;
/** The last time that this information was updated. This would typically have
been during a scan when this plugin was first tested or found to have changed.
*/
Time lastInfoUpdateTime;
/** A unique ID for the plug-in.
Note that this might not be unique between formats, e.g. a VST and some
other format might actually have the same id.
@see createIdentifierString
*/
int uid;
/** True if the plug-in identifies itself as a synthesiser. */
bool isInstrument;
/** The number of inputs. */
int numInputChannels;
/** The number of outputs. */
int numOutputChannels;
/** True if the plug-in is part of a multi-type container, e.g. a VST Shell. */
bool hasSharedContainer;
/** Returns true if the two descriptions refer to the same plug-in.
This isn't quite as simple as them just having the same file (because of
shell plug-ins).
*/
bool isDuplicateOf (const PluginDescription& other) const noexcept;
/** Return true if this description is equivalent to another one which created the
given identifier string.
Note that this isn't quite as simple as them just calling createIdentifierString()
and comparing the strings, because the identifiers can differ (thanks to shell plug-ins).
*/
bool matchesIdentifierString (const String& identifierString) const;
//==============================================================================
/** Returns a string that can be saved and used to uniquely identify the
plugin again.
This contains less info than the XML encoding, and is independent of the
plug-in's file location, so can be used to store a plug-in ID for use
across different machines.
*/
String createIdentifierString() const;
//==============================================================================
/** Creates an XML object containing these details.
@see loadFromXml
*/
XmlElement* createXml() const;
/** Reloads the info in this structure from an XML record that was previously
saved with createXML().
Returns true if the XML was a valid plug-in description.
*/
bool loadFromXml (const XmlElement& xml);
private:
//==============================================================================
JUCE_LEAK_DETECTOR (PluginDescription)
};
} // namespace juce

+ 0
- 587
source/modules/juce_audio_processors/scanning/juce_KnownPluginList.cpp View File

@@ -1,587 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
KnownPluginList::KnownPluginList() {}
KnownPluginList::~KnownPluginList() {}
void KnownPluginList::clear()
{
ScopedLock lock (typesArrayLock);
if (! types.isEmpty())
{
types.clear();
sendChangeMessage();
}
}
PluginDescription* KnownPluginList::getTypeForFile (const String& fileOrIdentifier) const
{
ScopedLock lock (typesArrayLock);
for (auto* desc : types)
if (desc->fileOrIdentifier == fileOrIdentifier)
return desc;
return nullptr;
}
PluginDescription* KnownPluginList::getTypeForIdentifierString (const String& identifierString) const
{
ScopedLock lock (typesArrayLock);
for (auto* desc : types)
if (desc->matchesIdentifierString (identifierString))
return desc;
return nullptr;
}
bool KnownPluginList::addType (const PluginDescription& type)
{
{
ScopedLock lock (typesArrayLock);
for (auto* desc : types)
{
if (desc->isDuplicateOf (type))
{
// strange - found a duplicate plugin with different info..
jassert (desc->name == type.name);
jassert (desc->isInstrument == type.isInstrument);
*desc = type;
return false;
}
}
types.insert (0, new PluginDescription (type));
}
sendChangeMessage();
return true;
}
void KnownPluginList::removeType (const int index)
{
{
ScopedLock lock (typesArrayLock);
types.remove (index);
}
sendChangeMessage();
}
bool KnownPluginList::isListingUpToDate (const String& fileOrIdentifier,
AudioPluginFormat& formatToUse) const
{
if (getTypeForFile (fileOrIdentifier) == nullptr)
return false;
ScopedLock lock (typesArrayLock);
for (auto* d : types)
if (d->fileOrIdentifier == fileOrIdentifier && formatToUse.pluginNeedsRescanning (*d))
return false;
return true;
}
void KnownPluginList::setCustomScanner (CustomScanner* newScanner)
{
scanner = newScanner;
}
bool KnownPluginList::scanAndAddFile (const String& fileOrIdentifier,
const bool dontRescanIfAlreadyInList,
OwnedArray<PluginDescription>& typesFound,
AudioPluginFormat& format)
{
const ScopedLock sl (scanLock);
if (dontRescanIfAlreadyInList
&& getTypeForFile (fileOrIdentifier) != nullptr)
{
bool needsRescanning = false;
ScopedLock lock (typesArrayLock);
for (auto* d : types)
{
if (d->fileOrIdentifier == fileOrIdentifier && d->pluginFormatName == format.getName())
{
if (format.pluginNeedsRescanning (*d))
needsRescanning = true;
else
typesFound.add (new PluginDescription (*d));
}
}
if (! needsRescanning)
return false;
}
if (blacklist.contains (fileOrIdentifier))
return false;
OwnedArray<PluginDescription> found;
{
const ScopedUnlock sl2 (scanLock);
if (scanner != nullptr)
{
if (! scanner->findPluginTypesFor (format, found, fileOrIdentifier))
addToBlacklist (fileOrIdentifier);
}
else
{
format.findAllTypesForFile (found, fileOrIdentifier);
}
}
for (auto* desc : found)
{
jassert (desc != nullptr);
addType (*desc);
typesFound.add (new PluginDescription (*desc));
}
return ! found.isEmpty();
}
void KnownPluginList::scanAndAddDragAndDroppedFiles (AudioPluginFormatManager& formatManager,
const StringArray& files,
OwnedArray<PluginDescription>& typesFound)
{
for (const auto& filenameOrID : files)
{
bool found = false;
for (int j = 0; j < formatManager.getNumFormats(); ++j)
{
auto* format = formatManager.getFormat (j);
if (format->fileMightContainThisPluginType (filenameOrID)
&& scanAndAddFile (filenameOrID, true, typesFound, *format))
{
found = true;
break;
}
}
if (! found)
{
const File f (filenameOrID);
if (f.isDirectory())
{
StringArray s;
{
Array<File> subFiles;
f.findChildFiles (subFiles, File::findFilesAndDirectories, false);
for (auto& subFile : subFiles)
s.add (subFile.getFullPathName());
}
scanAndAddDragAndDroppedFiles (formatManager, s, typesFound);
}
}
}
scanFinished();
}
void KnownPluginList::scanFinished()
{
if (scanner != nullptr)
scanner->scanFinished();
}
const StringArray& KnownPluginList::getBlacklistedFiles() const
{
return blacklist;
}
void KnownPluginList::addToBlacklist (const String& pluginID)
{
if (! blacklist.contains (pluginID))
{
blacklist.add (pluginID);
sendChangeMessage();
}
}
void KnownPluginList::removeFromBlacklist (const String& pluginID)
{
const int index = blacklist.indexOf (pluginID);
if (index >= 0)
{
blacklist.remove (index);
sendChangeMessage();
}
}
void KnownPluginList::clearBlacklistedFiles()
{
if (blacklist.size() > 0)
{
blacklist.clear();
sendChangeMessage();
}
}
//==============================================================================
struct PluginSorter
{
PluginSorter (KnownPluginList::SortMethod sortMethod, bool forwards) noexcept
: method (sortMethod), direction (forwards ? 1 : -1) {}
int compareElements (const PluginDescription* const first,
const PluginDescription* const second) const
{
int diff = 0;
switch (method)
{
case KnownPluginList::sortByCategory: diff = first->category.compareNatural (second->category, true); break;
case KnownPluginList::sortByManufacturer: diff = first->manufacturerName.compareNatural (second->manufacturerName, true); break;
case KnownPluginList::sortByFormat: diff = first->pluginFormatName.compare (second->pluginFormatName); break;
case KnownPluginList::sortByFileSystemLocation: diff = lastPathPart (first->fileOrIdentifier).compare (lastPathPart (second->fileOrIdentifier)); break;
case KnownPluginList::sortByInfoUpdateTime: diff = compare (first->lastInfoUpdateTime, second->lastInfoUpdateTime); break;
default: break;
}
if (diff == 0)
diff = first->name.compareNatural (second->name, true);
return diff * direction;
}
private:
static String lastPathPart (const String& path)
{
return path.replaceCharacter ('\\', '/').upToLastOccurrenceOf ("/", false, false);
}
static int compare (Time a, Time b) noexcept
{
if (a < b) return -1;
if (b < a) return 1;
return 0;
}
const KnownPluginList::SortMethod method;
const int direction;
JUCE_DECLARE_NON_COPYABLE (PluginSorter)
};
void KnownPluginList::sort (const SortMethod method, bool forwards)
{
if (method != defaultOrder)
{
Array<PluginDescription*> oldOrder, newOrder;
{
ScopedLock lock (typesArrayLock);
oldOrder.addArray (types);
PluginSorter sorter (method, forwards);
types.sort (sorter, true);
newOrder.addArray (types);
}
if (oldOrder != newOrder)
sendChangeMessage();
}
}
//==============================================================================
XmlElement* KnownPluginList::createXml() const
{
auto e = new XmlElement ("KNOWNPLUGINS");
{
ScopedLock lock (typesArrayLock);
for (int i = types.size(); --i >= 0;)
e->prependChildElement (types.getUnchecked(i)->createXml());
}
for (auto& b : blacklist)
e->createNewChildElement ("BLACKLISTED")->setAttribute ("id", b);
return e;
}
void KnownPluginList::recreateFromXml (const XmlElement& xml)
{
clear();
clearBlacklistedFiles();
if (xml.hasTagName ("KNOWNPLUGINS"))
{
forEachXmlChildElement (xml, e)
{
PluginDescription info;
if (e->hasTagName ("BLACKLISTED"))
blacklist.add (e->getStringAttribute ("id"));
else if (info.loadFromXml (*e))
addType (info);
}
}
}
//==============================================================================
struct PluginTreeUtils
{
enum { menuIdBase = 0x324503f4 };
static void buildTreeByFolder (KnownPluginList::PluginTree& tree, const Array<PluginDescription*>& allPlugins)
{
for (auto* pd : allPlugins)
{
auto path = pd->fileOrIdentifier.replaceCharacter ('\\', '/')
.upToLastOccurrenceOf ("/", false, false);
if (path.substring (1, 2) == ":")
path = path.substring (2);
addPlugin (tree, pd, path);
}
optimiseFolders (tree, false);
}
static void optimiseFolders (KnownPluginList::PluginTree& tree, bool concatenateName)
{
for (int i = tree.subFolders.size(); --i >= 0;)
{
auto& sub = *tree.subFolders.getUnchecked(i);
optimiseFolders (sub, concatenateName || (tree.subFolders.size() > 1));
if (sub.plugins.isEmpty())
{
for (auto* s : sub.subFolders)
{
if (concatenateName)
s->folder = sub.folder + "/" + s->folder;
tree.subFolders.add (s);
}
sub.subFolders.clear (false);
tree.subFolders.remove (i);
}
}
}
static void buildTreeByCategory (KnownPluginList::PluginTree& tree,
const Array<PluginDescription*>& sorted,
const KnownPluginList::SortMethod sortMethod)
{
String lastType;
ScopedPointer<KnownPluginList::PluginTree> current (new KnownPluginList::PluginTree());
for (auto* pd : sorted)
{
auto thisType = (sortMethod == KnownPluginList::sortByCategory ? pd->category
: pd->manufacturerName);
if (! thisType.containsNonWhitespaceChars())
thisType = "Other";
if (! thisType.equalsIgnoreCase (lastType))
{
if (current->plugins.size() + current->subFolders.size() > 0)
{
current->folder = lastType;
tree.subFolders.add (current.release());
current = new KnownPluginList::PluginTree();
}
lastType = thisType;
}
current->plugins.add (pd);
}
if (current->plugins.size() + current->subFolders.size() > 0)
{
current->folder = lastType;
tree.subFolders.add (current.release());
}
}
static void addPlugin (KnownPluginList::PluginTree& tree, PluginDescription* const pd, String path)
{
if (path.isEmpty())
{
tree.plugins.add (pd);
}
else
{
#if JUCE_MAC
if (path.containsChar (':'))
path = path.fromFirstOccurrenceOf (":", false, false); // avoid the special AU formatting nonsense on Mac..
#endif
auto firstSubFolder = path.upToFirstOccurrenceOf ("/", false, false);
auto remainingPath = path.fromFirstOccurrenceOf ("/", false, false);
for (int i = tree.subFolders.size(); --i >= 0;)
{
KnownPluginList::PluginTree& subFolder = *tree.subFolders.getUnchecked(i);
if (subFolder.folder.equalsIgnoreCase (firstSubFolder))
{
addPlugin (subFolder, pd, remainingPath);
return;
}
}
auto newFolder = new KnownPluginList::PluginTree();
newFolder->folder = firstSubFolder;
tree.subFolders.add (newFolder);
addPlugin (*newFolder, pd, remainingPath);
}
}
static bool containsDuplicateNames (const Array<const PluginDescription*>& plugins, const String& name)
{
int matches = 0;
for (int i = 0; i < plugins.size(); ++i)
if (plugins.getUnchecked(i)->name == name)
if (++matches > 1)
return true;
return false;
}
static bool addToMenu (const KnownPluginList::PluginTree& tree, PopupMenu& m,
const OwnedArray<PluginDescription>& allPlugins,
const String& currentlyTickedPluginID)
{
bool isTicked = false;
for (auto* sub : tree.subFolders)
{
PopupMenu subMenu;
const bool isItemTicked = addToMenu (*sub, subMenu, allPlugins, currentlyTickedPluginID);
isTicked = isTicked || isItemTicked;
m.addSubMenu (sub->folder, subMenu, true, nullptr, isItemTicked, 0);
}
for (auto* plugin : tree.plugins)
{
auto name = plugin->name;
if (containsDuplicateNames (tree.plugins, name))
name << " (" << plugin->pluginFormatName << ')';
const bool isItemTicked = plugin->matchesIdentifierString (currentlyTickedPluginID);
isTicked = isTicked || isItemTicked;
m.addItem (allPlugins.indexOf (plugin) + menuIdBase, name, true, isItemTicked);
}
return isTicked;
}
};
KnownPluginList::PluginTree* KnownPluginList::createTree (const SortMethod sortMethod) const
{
Array<PluginDescription*> sorted;
{
ScopedLock lock (typesArrayLock);
PluginSorter sorter (sortMethod, true);
for (auto* t : types)
sorted.addSorted (sorter, t);
}
auto* tree = new PluginTree();
if (sortMethod == sortByCategory || sortMethod == sortByManufacturer || sortMethod == sortByFormat)
{
PluginTreeUtils::buildTreeByCategory (*tree, sorted, sortMethod);
}
else if (sortMethod == sortByFileSystemLocation)
{
PluginTreeUtils::buildTreeByFolder (*tree, sorted);
}
else
{
for (auto* p : sorted)
tree->plugins.add (p);
}
return tree;
}
//==============================================================================
void KnownPluginList::addToMenu (PopupMenu& menu, const SortMethod sortMethod,
const String& currentlyTickedPluginID) const
{
ScopedPointer<PluginTree> tree (createTree (sortMethod));
PluginTreeUtils::addToMenu (*tree, menu, types, currentlyTickedPluginID);
}
int KnownPluginList::getIndexChosenByMenu (const int menuResultCode) const
{
const int i = menuResultCode - PluginTreeUtils::menuIdBase;
return isPositiveAndBelow (i, types.size()) ? i : -1;
}
//==============================================================================
KnownPluginList::CustomScanner::CustomScanner() {}
KnownPluginList::CustomScanner::~CustomScanner() {}
void KnownPluginList::CustomScanner::scanFinished() {}
bool KnownPluginList::CustomScanner::shouldExit() const noexcept
{
if (auto* job = ThreadPoolJob::getCurrentThreadPoolJob())
return job->shouldExit();
return false;
}
} // namespace juce

+ 0
- 225
source/modules/juce_audio_processors/scanning/juce_KnownPluginList.h View File

@@ -1,225 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
Manages a list of plugin types.
This can be easily edited, saved and loaded, and used to create instances of
the plugin types in it.
@see PluginListComponent
*/
class JUCE_API KnownPluginList : public ChangeBroadcaster
{
public:
//==============================================================================
/** Creates an empty list. */
KnownPluginList();
/** Destructor. */
~KnownPluginList();
//==============================================================================
/** Clears the list. */
void clear();
/** Returns the number of types currently in the list.
@see getType
*/
int getNumTypes() const noexcept { return types.size(); }
/** Returns one of the types.
@see getNumTypes
*/
PluginDescription* getType (int index) const noexcept { return types [index]; }
/** Type iteration. */
PluginDescription** begin() const noexcept { return types.begin(); }
/** Type iteration. */
PluginDescription** end() const noexcept { return types.end(); }
/** Looks for a type in the list which comes from this file. */
PluginDescription* getTypeForFile (const String& fileOrIdentifier) const;
/** Looks for a type in the list which matches a plugin type ID.
The identifierString parameter must have been created by
PluginDescription::createIdentifierString().
*/
PluginDescription* getTypeForIdentifierString (const String& identifierString) const;
/** Adds a type manually from its description. */
bool addType (const PluginDescription& type);
/** Removes a type. */
void removeType (int index);
/** Looks for all types that can be loaded from a given file, and adds them
to the list.
If dontRescanIfAlreadyInList is true, then the file will only be loaded and
re-tested if it's not already in the list, or if the file's modification
time has changed since the list was created. If dontRescanIfAlreadyInList is
false, the file will always be reloaded and tested.
Returns true if any new types were added, and all the types found in this
file (even if it was already known and hasn't been re-scanned) get returned
in the array.
*/
bool scanAndAddFile (const String& possiblePluginFileOrIdentifier,
bool dontRescanIfAlreadyInList,
OwnedArray <PluginDescription>& typesFound,
AudioPluginFormat& formatToUse);
/** Tells a custom scanner that a scan has finished, and it can release any resources. */
void scanFinished();
/** Returns true if the specified file is already known about and if it
hasn't been modified since our entry was created.
*/
bool isListingUpToDate (const String& possiblePluginFileOrIdentifier,
AudioPluginFormat& formatToUse) const;
/** Scans and adds a bunch of files that might have been dragged-and-dropped.
If any types are found in the files, their descriptions are returned in the array.
*/
void scanAndAddDragAndDroppedFiles (AudioPluginFormatManager& formatManager,
const StringArray& filenames,
OwnedArray <PluginDescription>& typesFound);
//==============================================================================
/** Returns the list of blacklisted files. */
const StringArray& getBlacklistedFiles() const;
/** Adds a plugin ID to the black-list. */
void addToBlacklist (const String& pluginID);
/** Removes a plugin ID from the black-list. */
void removeFromBlacklist (const String& pluginID);
/** Clears all the blacklisted files. */
void clearBlacklistedFiles();
//==============================================================================
/** Sort methods used to change the order of the plugins in the list.
*/
enum SortMethod
{
defaultOrder = 0,
sortAlphabetically,
sortByCategory,
sortByManufacturer,
sortByFormat,
sortByFileSystemLocation,
sortByInfoUpdateTime
};
//==============================================================================
/** Adds all the plugin types to a popup menu so that the user can select one.
Depending on the sort method, it may add sub-menus for categories,
manufacturers, etc.
Use getIndexChosenByMenu() to find out the type that was chosen.
*/
void addToMenu (PopupMenu& menu, SortMethod sortMethod,
const String& currentlyTickedPluginID = String()) const;
/** Converts a menu item index that has been chosen into its index in this list.
Returns -1 if it's not an ID that was used.
@see addToMenu
*/
int getIndexChosenByMenu (int menuResultCode) const;
//==============================================================================
/** Sorts the list. */
void sort (SortMethod method, bool forwards);
//==============================================================================
/** Creates some XML that can be used to store the state of this list. */
XmlElement* createXml() const;
/** Recreates the state of this list from its stored XML format. */
void recreateFromXml (const XmlElement& xml);
//==============================================================================
/** A structure that recursively holds a tree of plugins.
@see KnownPluginList::createTree()
*/
struct PluginTree
{
String folder; /**< The name of this folder in the tree */
OwnedArray<PluginTree> subFolders;
Array<const PluginDescription*> plugins;
};
/** Creates a PluginTree object containing all the known plugins. */
PluginTree* createTree (const SortMethod sortMethod) const;
//==============================================================================
class CustomScanner
{
public:
CustomScanner();
virtual ~CustomScanner();
/** Attempts to load the given file and find a list of plugins in it.
@returns true if the plugin loaded, false if it crashed
*/
virtual bool findPluginTypesFor (AudioPluginFormat& format,
OwnedArray <PluginDescription>& result,
const String& fileOrIdentifier) = 0;
/** Called when a scan has finished, to allow clean-up of resources. */
virtual void scanFinished();
/** Returns true if the current scan should be abandoned.
Any blocking methods should check this value repeatedly and return if
if becomes true.
*/
bool shouldExit() const noexcept;
};
/** Supplies a custom scanner to be used in future scans.
The KnownPluginList will take ownership of the object passed in.
*/
void setCustomScanner (CustomScanner*);
private:
//==============================================================================
OwnedArray<PluginDescription> types;
StringArray blacklist;
ScopedPointer<CustomScanner> scanner;
CriticalSection scanLock, typesArrayLock;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (KnownPluginList)
};
} // namespace juce

+ 0
- 136
source/modules/juce_audio_processors/scanning/juce_PluginDirectoryScanner.cpp View File

@@ -1,136 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
static StringArray readDeadMansPedalFile (const File& file)
{
StringArray lines;
file.readLines (lines);
lines.removeEmptyStrings();
return lines;
}
PluginDirectoryScanner::PluginDirectoryScanner (KnownPluginList& listToAddTo,
AudioPluginFormat& formatToLookFor,
FileSearchPath directoriesToSearch,
const bool recursive,
const File& deadMansPedal,
bool allowPluginsWhichRequireAsynchronousInstantiation)
: list (listToAddTo),
format (formatToLookFor),
deadMansPedalFile (deadMansPedal),
allowAsync (allowPluginsWhichRequireAsynchronousInstantiation)
{
directoriesToSearch.removeRedundantPaths();
filesOrIdentifiersToScan = format.searchPathsForPlugins (directoriesToSearch, recursive, allowAsync);
// If any plugins have crashed recently when being loaded, move them to the
// end of the list to give the others a chance to load correctly..
for (auto& crashed : readDeadMansPedalFile (deadMansPedalFile))
for (int j = filesOrIdentifiersToScan.size(); --j >= 0;)
if (crashed == filesOrIdentifiersToScan[j])
filesOrIdentifiersToScan.move (j, -1);
applyBlacklistingsFromDeadMansPedal (listToAddTo, deadMansPedalFile);
nextIndex.set (filesOrIdentifiersToScan.size());
}
PluginDirectoryScanner::~PluginDirectoryScanner()
{
list.scanFinished();
}
//==============================================================================
String PluginDirectoryScanner::getNextPluginFileThatWillBeScanned() const
{
return format.getNameOfPluginFromIdentifier (filesOrIdentifiersToScan [nextIndex.get() - 1]);
}
void PluginDirectoryScanner::updateProgress()
{
progress = (1.0f - nextIndex.get() / (float) filesOrIdentifiersToScan.size());
}
bool PluginDirectoryScanner::scanNextFile (bool dontRescanIfAlreadyInList,
String& nameOfPluginBeingScanned)
{
const int index = --nextIndex;
if (index >= 0)
{
auto file = filesOrIdentifiersToScan [index];
if (file.isNotEmpty() && ! (dontRescanIfAlreadyInList && list.isListingUpToDate (file, format)))
{
nameOfPluginBeingScanned = format.getNameOfPluginFromIdentifier (file);
OwnedArray<PluginDescription> typesFound;
// Add this plugin to the end of the dead-man's pedal list in case it crashes...
auto crashedPlugins = readDeadMansPedalFile (deadMansPedalFile);
crashedPlugins.removeString (file);
crashedPlugins.add (file);
setDeadMansPedalFile (crashedPlugins);
list.scanAndAddFile (file, dontRescanIfAlreadyInList, typesFound, format);
// Managed to load without crashing, so remove it from the dead-man's-pedal..
crashedPlugins.removeString (file);
setDeadMansPedalFile (crashedPlugins);
if (typesFound.size() == 0 && ! list.getBlacklistedFiles().contains (file))
failedFiles.add (file);
}
}
updateProgress();
return index > 0;
}
bool PluginDirectoryScanner::skipNextFile()
{
updateProgress();
return --nextIndex > 0;
}
void PluginDirectoryScanner::setDeadMansPedalFile (const StringArray& newContents)
{
if (deadMansPedalFile.getFullPathName().isNotEmpty())
deadMansPedalFile.replaceWithText (newContents.joinIntoString ("\n"), true, true);
}
void PluginDirectoryScanner::applyBlacklistingsFromDeadMansPedal (KnownPluginList& list, const File& file)
{
// If any plugins have crashed recently when being loaded, move them to the
// end of the list to give the others a chance to load correctly..
for (auto& crashedPlugin : readDeadMansPedalFile (file))
list.addToBlacklist (crashedPlugin);
}
} // namespace juce

+ 0
- 131
source/modules/juce_audio_processors/scanning/juce_PluginDirectoryScanner.h View File

@@ -1,131 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
Scans a directory for plugins, and adds them to a KnownPluginList.
To use one of these, create it and call scanNextFile() repeatedly, until
it returns false.
*/
class JUCE_API PluginDirectoryScanner
{
public:
//==============================================================================
/**
Creates a scanner.
@param listToAddResultsTo this will get the new types added to it.
@param formatToLookFor this is the type of format that you want to look for
@param directoriesToSearch the path to search
@param searchRecursively true to search recursively
@param deadMansPedalFile if this isn't File(), then it will be used as a file
to store the names of any plugins that crash during
initialisation. If there are any plugins listed in it,
then these will always be scanned after all other possible
files have been tried - in this way, even if there's a few
dodgy plugins in your path, then a couple of rescans
will still manage to find all the proper plugins.
It's probably best to choose a file in the user's
application data directory (alongside your app's
settings file) for this. The file format it uses
is just a list of filenames of the modules that
failed.
@param allowPluginsWhichRequireAsynchronousInstantiation
If this is false then the scanner will exclude plug-ins
asynchronous creation - such as AUv3 plug-ins.
*/
PluginDirectoryScanner (KnownPluginList& listToAddResultsTo,
AudioPluginFormat& formatToLookFor,
FileSearchPath directoriesToSearch,
bool searchRecursively,
const File& deadMansPedalFile,
bool allowPluginsWhichRequireAsynchronousInstantiation = false);
/** Destructor. */
~PluginDirectoryScanner();
//==============================================================================
/** Tries the next likely-looking file.
If dontRescanIfAlreadyInList is true, then the file will only be loaded and
re-tested if it's not already in the list, or if the file's modification
time has changed since the list was created. If dontRescanIfAlreadyInList is
false, the file will always be reloaded and tested.
The nameOfPluginBeingScanned will be updated to the name of the plugin being
scanned before the scan starts.
Returns false when there are no more files to try.
*/
bool scanNextFile (bool dontRescanIfAlreadyInList,
String& nameOfPluginBeingScanned);
/** Skips over the next file without scanning it.
Returns false when there are no more files to try.
*/
bool skipNextFile();
/** Returns the description of the plugin that will be scanned during the next
call to scanNextFile().
This is handy if you want to show the user which file is currently getting
scanned.
*/
String getNextPluginFileThatWillBeScanned() const;
/** Returns the estimated progress, between 0 and 1. */
float getProgress() const { return progress; }
/** This returns a list of all the filenames of things that looked like being
a plugin file, but which failed to open for some reason.
*/
const StringArray& getFailedFiles() const noexcept { return failedFiles; }
/** Reads the given dead-mans-pedal file and applies its contents to the list. */
static void applyBlacklistingsFromDeadMansPedal (KnownPluginList& listToApplyTo,
const File& deadMansPedalFile);
private:
//==============================================================================
KnownPluginList& list;
AudioPluginFormat& format;
StringArray filesOrIdentifiersToScan;
File deadMansPedalFile;
StringArray failedFiles;
Atomic<int> nextIndex;
float progress = 0;
const bool allowAsync;
void updateProgress();
void setDeadMansPedalFile (const StringArray& newContents);
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PluginDirectoryScanner)
};
} // namespace juce

+ 0
- 593
source/modules/juce_audio_processors/scanning/juce_PluginListComponent.cpp View File

@@ -1,593 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
class PluginListComponent::TableModel : public TableListBoxModel
{
public:
TableModel (PluginListComponent& c, KnownPluginList& l) : owner (c), list (l) {}
int getNumRows() override
{
return list.getNumTypes() + list.getBlacklistedFiles().size();
}
void paintRowBackground (Graphics& g, int /*rowNumber*/, int /*width*/, int /*height*/, bool rowIsSelected) override
{
const auto defaultColour = owner.findColour (ListBox::backgroundColourId);
const auto c = rowIsSelected ? defaultColour.interpolatedWith (owner.findColour (ListBox::textColourId), 0.5f)
: defaultColour;
g.fillAll (c);
}
enum
{
nameCol = 1,
typeCol = 2,
categoryCol = 3,
manufacturerCol = 4,
descCol = 5
};
void paintCell (Graphics& g, int row, int columnId, int width, int height, bool /*rowIsSelected*/) override
{
String text;
bool isBlacklisted = row >= list.getNumTypes();
if (isBlacklisted)
{
if (columnId == nameCol)
text = list.getBlacklistedFiles() [row - list.getNumTypes()];
else if (columnId == descCol)
text = TRANS("Deactivated after failing to initialise correctly");
}
else if (const PluginDescription* const desc = list.getType (row))
{
switch (columnId)
{
case nameCol: text = desc->name; break;
case typeCol: text = desc->pluginFormatName; break;
case categoryCol: text = desc->category.isNotEmpty() ? desc->category : "-"; break;
case manufacturerCol: text = desc->manufacturerName; break;
case descCol: text = getPluginDescription (*desc); break;
default: jassertfalse; break;
}
}
if (text.isNotEmpty())
{
const auto defaultTextColour = owner.findColour (ListBox::textColourId);
g.setColour (isBlacklisted ? Colours::red
: columnId == nameCol ? defaultTextColour
: defaultTextColour.interpolatedWith (Colours::transparentBlack, 0.3f));
g.setFont (Font (height * 0.7f, Font::bold));
g.drawFittedText (text, 4, 0, width - 6, height, Justification::centredLeft, 1, 0.9f);
}
}
void deleteKeyPressed (int) override
{
owner.removeSelectedPlugins();
}
void sortOrderChanged (int newSortColumnId, bool isForwards) override
{
switch (newSortColumnId)
{
case nameCol: list.sort (KnownPluginList::sortAlphabetically, isForwards); break;
case typeCol: list.sort (KnownPluginList::sortByFormat, isForwards); break;
case categoryCol: list.sort (KnownPluginList::sortByCategory, isForwards); break;
case manufacturerCol: list.sort (KnownPluginList::sortByManufacturer, isForwards); break;
case descCol: break;
default: jassertfalse; break;
}
}
static String getPluginDescription (const PluginDescription& desc)
{
StringArray items;
if (desc.descriptiveName != desc.name)
items.add (desc.descriptiveName);
items.add (desc.version);
items.removeEmptyStrings();
return items.joinIntoString (" - ");
}
PluginListComponent& owner;
KnownPluginList& list;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TableModel)
};
//==============================================================================
PluginListComponent::PluginListComponent (AudioPluginFormatManager& manager, KnownPluginList& listToEdit,
const File& deadMansPedal, PropertiesFile* const props,
bool allowPluginsWhichRequireAsynchronousInstantiation)
: formatManager (manager),
list (listToEdit),
deadMansPedalFile (deadMansPedal),
optionsButton ("Options..."),
propertiesToUse (props),
allowAsync (allowPluginsWhichRequireAsynchronousInstantiation),
numThreads (allowAsync ? 1 : 0)
{
tableModel = new TableModel (*this, listToEdit);
TableHeaderComponent& header = table.getHeader();
header.addColumn (TRANS("Name"), TableModel::nameCol, 200, 100, 700, TableHeaderComponent::defaultFlags | TableHeaderComponent::sortedForwards);
header.addColumn (TRANS("Format"), TableModel::typeCol, 80, 80, 80, TableHeaderComponent::notResizable);
header.addColumn (TRANS("Category"), TableModel::categoryCol, 100, 100, 200);
header.addColumn (TRANS("Manufacturer"), TableModel::manufacturerCol, 200, 100, 300);
header.addColumn (TRANS("Description"), TableModel::descCol, 300, 100, 500, TableHeaderComponent::notSortable);
table.setHeaderHeight (22);
table.setRowHeight (20);
table.setModel (tableModel);
table.setMultipleSelectionEnabled (true);
addAndMakeVisible (table);
addAndMakeVisible (optionsButton);
optionsButton.addListener (this);
optionsButton.setTriggeredOnMouseDown (true);
setSize (400, 600);
list.addChangeListener (this);
updateList();
table.getHeader().reSortTable();
PluginDirectoryScanner::applyBlacklistingsFromDeadMansPedal (list, deadMansPedalFile);
deadMansPedalFile.deleteFile();
}
PluginListComponent::~PluginListComponent()
{
list.removeChangeListener (this);
}
void PluginListComponent::setOptionsButtonText (const String& newText)
{
optionsButton.setButtonText (newText);
resized();
}
void PluginListComponent::setScanDialogText (const String& title, const String& content)
{
dialogTitle = title;
dialogText = content;
}
void PluginListComponent::setNumberOfThreadsForScanning (int num)
{
numThreads = num;
}
void PluginListComponent::resized()
{
Rectangle<int> r (getLocalBounds().reduced (2));
optionsButton.setBounds (r.removeFromBottom (24));
optionsButton.changeWidthToFitText (24);
r.removeFromBottom (3);
table.setBounds (r);
}
void PluginListComponent::changeListenerCallback (ChangeBroadcaster*)
{
table.getHeader().reSortTable();
updateList();
}
void PluginListComponent::updateList()
{
table.updateContent();
table.repaint();
}
void PluginListComponent::removeSelectedPlugins()
{
const SparseSet<int> selected (table.getSelectedRows());
for (int i = table.getNumRows(); --i >= 0;)
if (selected.contains (i))
removePluginItem (i);
}
void PluginListComponent::setTableModel (TableListBoxModel* model)
{
table.setModel (nullptr);
tableModel = model;
table.setModel (tableModel);
table.getHeader().reSortTable();
table.updateContent();
table.repaint();
}
bool PluginListComponent::canShowSelectedFolder() const
{
if (const PluginDescription* const desc = list.getType (table.getSelectedRow()))
return File::createFileWithoutCheckingPath (desc->fileOrIdentifier).exists();
return false;
}
void PluginListComponent::showSelectedFolder()
{
if (canShowSelectedFolder())
if (const PluginDescription* const desc = list.getType (table.getSelectedRow()))
File (desc->fileOrIdentifier).getParentDirectory().startAsProcess();
}
void PluginListComponent::removeMissingPlugins()
{
for (int i = list.getNumTypes(); --i >= 0;)
if (! formatManager.doesPluginStillExist (*list.getType (i)))
list.removeType (i);
}
void PluginListComponent::removePluginItem (int index)
{
if (index < list.getNumTypes())
list.removeType (index);
else
list.removeFromBlacklist (list.getBlacklistedFiles() [index - list.getNumTypes()]);
}
void PluginListComponent::optionsMenuStaticCallback (int result, PluginListComponent* pluginList)
{
if (pluginList != nullptr)
pluginList->optionsMenuCallback (result);
}
void PluginListComponent::optionsMenuCallback (int result)
{
switch (result)
{
case 0: break;
case 1: list.clear(); break;
case 2: removeSelectedPlugins(); break;
case 3: showSelectedFolder(); break;
case 4: removeMissingPlugins(); break;
default:
if (AudioPluginFormat* format = formatManager.getFormat (result - 10))
scanFor (*format);
break;
}
}
void PluginListComponent::buttonClicked (Button* button)
{
if (button == &optionsButton)
{
PopupMenu menu;
menu.addItem (1, TRANS("Clear list"));
menu.addItem (2, TRANS("Remove selected plug-in from list"), table.getNumSelectedRows() > 0);
menu.addItem (3, TRANS("Show folder containing selected plug-in"), canShowSelectedFolder());
menu.addItem (4, TRANS("Remove any plug-ins whose files no longer exist"));
menu.addSeparator();
for (int i = 0; i < formatManager.getNumFormats(); ++i)
{
AudioPluginFormat* const format = formatManager.getFormat (i);
if (format->canScanForPlugins())
menu.addItem (10 + i, "Scan for new or updated " + format->getName() + " plug-ins");
}
menu.showMenuAsync (PopupMenu::Options().withTargetComponent (&optionsButton),
ModalCallbackFunction::forComponent (optionsMenuStaticCallback, this));
}
}
bool PluginListComponent::isInterestedInFileDrag (const StringArray& /*files*/)
{
return true;
}
void PluginListComponent::filesDropped (const StringArray& files, int, int)
{
OwnedArray<PluginDescription> typesFound;
list.scanAndAddDragAndDroppedFiles (formatManager, files, typesFound);
}
FileSearchPath PluginListComponent::getLastSearchPath (PropertiesFile& properties, AudioPluginFormat& format)
{
return FileSearchPath (properties.getValue ("lastPluginScanPath_" + format.getName(),
format.getDefaultLocationsToSearch().toString()));
}
void PluginListComponent::setLastSearchPath (PropertiesFile& properties, AudioPluginFormat& format,
const FileSearchPath& newPath)
{
properties.setValue ("lastPluginScanPath_" + format.getName(), newPath.toString());
}
//==============================================================================
class PluginListComponent::Scanner : private Timer
{
public:
Scanner (PluginListComponent& plc, AudioPluginFormat& format, PropertiesFile* properties,
bool allowPluginsWhichRequireAsynchronousInstantiation, int threads,
const String& title, const String& text)
: owner (plc), formatToScan (format), propertiesToUse (properties),
pathChooserWindow (TRANS("Select folders to scan..."), String(), AlertWindow::NoIcon),
progressWindow (title, text, AlertWindow::NoIcon),
progress (0.0), numThreads (threads), allowAsync (allowPluginsWhichRequireAsynchronousInstantiation),
finished (false)
{
FileSearchPath path (formatToScan.getDefaultLocationsToSearch());
// You need to use at least one thread when scanning plug-ins asynchronously
jassert (! allowAsync || (numThreads > 0));
if (path.getNumPaths() > 0) // if the path is empty, then paths aren't used for this format.
{
#if ! JUCE_IOS
if (propertiesToUse != nullptr)
path = getLastSearchPath (*propertiesToUse, formatToScan);
#endif
pathList.setSize (500, 300);
pathList.setPath (path);
pathChooserWindow.addCustomComponent (&pathList);
pathChooserWindow.addButton (TRANS("Scan"), 1, KeyPress (KeyPress::returnKey));
pathChooserWindow.addButton (TRANS("Cancel"), 0, KeyPress (KeyPress::escapeKey));
pathChooserWindow.enterModalState (true,
ModalCallbackFunction::forComponent (startScanCallback,
&pathChooserWindow, this),
false);
}
else
{
startScan();
}
}
~Scanner()
{
if (pool != nullptr)
{
pool->removeAllJobs (true, 60000);
pool = nullptr;
}
}
private:
PluginListComponent& owner;
AudioPluginFormat& formatToScan;
PropertiesFile* propertiesToUse;
ScopedPointer<PluginDirectoryScanner> scanner;
AlertWindow pathChooserWindow, progressWindow;
FileSearchPathListComponent pathList;
String pluginBeingScanned;
double progress;
int numThreads;
bool allowAsync, finished;
ScopedPointer<ThreadPool> pool;
static void startScanCallback (int result, AlertWindow* alert, Scanner* scanner)
{
if (alert != nullptr && scanner != nullptr)
{
if (result != 0)
scanner->warnUserAboutStupidPaths();
else
scanner->finishedScan();
}
}
// Try to dissuade people from to scanning their entire C: drive, or other system folders.
void warnUserAboutStupidPaths()
{
for (int i = 0; i < pathList.getPath().getNumPaths(); ++i)
{
const File f (pathList.getPath()[i]);
if (isStupidPath (f))
{
AlertWindow::showOkCancelBox (AlertWindow::WarningIcon,
TRANS("Plugin Scanning"),
TRANS("If you choose to scan folders that contain non-plugin files, "
"then scanning may take a long time, and can cause crashes when "
"attempting to load unsuitable files.")
+ newLine
+ TRANS ("Are you sure you want to scan the folder \"XYZ\"?")
.replace ("XYZ", f.getFullPathName()),
TRANS ("Scan"),
String(),
nullptr,
ModalCallbackFunction::create (warnAboutStupidPathsCallback, this));
return;
}
}
startScan();
}
static bool isStupidPath (const File& f)
{
Array<File> roots;
File::findFileSystemRoots (roots);
if (roots.contains (f))
return true;
File::SpecialLocationType pathsThatWouldBeStupidToScan[]
= { File::globalApplicationsDirectory,
File::userHomeDirectory,
File::userDocumentsDirectory,
File::userDesktopDirectory,
File::tempDirectory,
File::userMusicDirectory,
File::userMoviesDirectory,
File::userPicturesDirectory };
for (int i = 0; i < numElementsInArray (pathsThatWouldBeStupidToScan); ++i)
{
const File sillyFolder (File::getSpecialLocation (pathsThatWouldBeStupidToScan[i]));
if (f == sillyFolder || sillyFolder.isAChildOf (f))
return true;
}
return false;
}
static void warnAboutStupidPathsCallback (int result, Scanner* scanner)
{
if (result != 0)
scanner->startScan();
else
scanner->finishedScan();
}
void startScan()
{
pathChooserWindow.setVisible (false);
scanner = new PluginDirectoryScanner (owner.list, formatToScan, pathList.getPath(),
true, owner.deadMansPedalFile, allowAsync);
if (propertiesToUse != nullptr)
{
setLastSearchPath (*propertiesToUse, formatToScan, pathList.getPath());
propertiesToUse->saveIfNeeded();
}
progressWindow.addButton (TRANS("Cancel"), 0, KeyPress (KeyPress::escapeKey));
progressWindow.addProgressBarComponent (progress);
progressWindow.enterModalState();
if (numThreads > 0)
{
pool = new ThreadPool (numThreads);
for (int i = numThreads; --i >= 0;)
pool->addJob (new ScanJob (*this), true);
}
startTimer (20);
}
void finishedScan()
{
owner.scanFinished (scanner != nullptr ? scanner->getFailedFiles()
: StringArray());
}
void timerCallback() override
{
if (pool == nullptr)
{
if (doNextScan())
startTimer (20);
}
if (! progressWindow.isCurrentlyModal())
finished = true;
if (finished)
finishedScan();
else
progressWindow.setMessage (TRANS("Testing") + ":\n\n" + pluginBeingScanned);
}
bool doNextScan()
{
if (scanner->scanNextFile (true, pluginBeingScanned))
{
progress = scanner->getProgress();
return true;
}
finished = true;
return false;
}
struct ScanJob : public ThreadPoolJob
{
ScanJob (Scanner& s) : ThreadPoolJob ("pluginscan"), scanner (s) {}
JobStatus runJob()
{
while (scanner.doNextScan() && ! shouldExit())
{}
return jobHasFinished;
}
Scanner& scanner;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ScanJob)
};
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Scanner)
};
void PluginListComponent::scanFor (AudioPluginFormat& format)
{
currentScanner = new Scanner (*this, format, propertiesToUse, allowAsync, numThreads,
dialogTitle.isNotEmpty() ? dialogTitle : TRANS("Scanning for plug-ins..."),
dialogText.isNotEmpty() ? dialogText : TRANS("Searching for all possible plug-in files..."));
}
bool PluginListComponent::isScanning() const noexcept
{
return currentScanner != nullptr;
}
void PluginListComponent::scanFinished (const StringArray& failedFiles)
{
StringArray shortNames;
for (int i = 0; i < failedFiles.size(); ++i)
shortNames.add (File::createFileWithoutCheckingPath (failedFiles[i]).getFileName());
currentScanner = nullptr; // mustn't delete this before using the failed files array
if (shortNames.size() > 0)
AlertWindow::showMessageBoxAsync (AlertWindow::InfoIcon,
TRANS("Scan complete"),
TRANS("Note that the following files appeared to be plugin files, but failed to load correctly")
+ ":\n\n"
+ shortNames.joinIntoString (", "));
}
} // namespace juce

+ 0
- 132
source/modules/juce_audio_processors/scanning/juce_PluginListComponent.h View File

@@ -1,132 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
A component displaying a list of plugins, with options to scan for them,
add, remove and sort them.
*/
class JUCE_API PluginListComponent : public Component,
public FileDragAndDropTarget,
private ChangeListener,
private Button::Listener
{
public:
//==============================================================================
/**
Creates the list component.
For info about the deadMansPedalFile, see the PluginDirectoryScanner constructor.
The properties file, if supplied, is used to store the user's last search paths.
*/
PluginListComponent (AudioPluginFormatManager& formatManager,
KnownPluginList& listToRepresent,
const File& deadMansPedalFile,
PropertiesFile* propertiesToUse,
bool allowPluginsWhichRequireAsynchronousInstantiation = false);
/** Destructor. */
~PluginListComponent();
/** Changes the text in the panel's options button. */
void setOptionsButtonText (const String& newText);
/** Changes the text in the progress dialog box that is shown when scanning. */
void setScanDialogText (const String& textForProgressWindowTitle,
const String& textForProgressWindowDescription);
/** Sets how many threads to simultaneously scan for plugins.
If this is 0, then all scanning happens on the message thread (this is the default when
allowPluginsWhichRequireAsynchronousInstantiation is false). If
allowPluginsWhichRequireAsynchronousInstantiation is true then numThreads must not
be zero (it is one by default). */
void setNumberOfThreadsForScanning (int numThreads);
/** Returns the last search path stored in a given properties file for the specified format. */
static FileSearchPath getLastSearchPath (PropertiesFile&, AudioPluginFormat&);
/** Stores a search path in a properties file for the given format. */
static void setLastSearchPath (PropertiesFile&, AudioPluginFormat&, const FileSearchPath&);
/** Triggers an asynchronous scan for the given format. */
void scanFor (AudioPluginFormat&);
/** Returns true if there's currently a scan in progress. */
bool isScanning() const noexcept;
/** Removes the plugins currently selected in the table. */
void removeSelectedPlugins();
/** Sets a custom table model to be used.
This will take ownership of the model and delete it when no longer needed.
*/
void setTableModel (TableListBoxModel* model);
/** Returns the table used to display the plugin list. */
TableListBox& getTableListBox() noexcept { return table; }
private:
//==============================================================================
AudioPluginFormatManager& formatManager;
KnownPluginList& list;
File deadMansPedalFile;
TableListBox table;
TextButton optionsButton;
PropertiesFile* propertiesToUse;
String dialogTitle, dialogText;
bool allowAsync;
int numThreads;
class TableModel;
ScopedPointer<TableListBoxModel> tableModel;
class Scanner;
friend class Scanner;
friend struct ContainerDeletePolicy<Scanner>;
ScopedPointer<Scanner> currentScanner;
void scanFinished (const StringArray&);
static void optionsMenuStaticCallback (int, PluginListComponent*);
void optionsMenuCallback (int);
void updateList();
void showSelectedFolder();
bool canShowSelectedFolder() const;
void removeMissingPlugins();
void removePluginItem (int index);
void resized() override;
bool isInterestedInFileDrag (const StringArray&) override;
void filesDropped (const StringArray&, int, int) override;
void buttonClicked (Button*) override;
void changeListenerCallback (ChangeBroadcaster*) override;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PluginListComponent)
};
} // namespace juce

+ 0
- 71
source/modules/juce_audio_processors/utilities/juce_AudioParameterBool.h View File

@@ -1,71 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
/**
Provides a class of AudioProcessorParameter that can be used as a boolean value.
@see AudioParameterFloat, AudioParameterInt, AudioParameterChoice
*/
class JUCE_API AudioParameterBool : public AudioProcessorParameterWithID
{
public:
/** Creates a AudioParameterBool with an ID and name.
On creation, its value is set to the default value.
*/
AudioParameterBool (const String& parameterID, const String& name, bool defaultValue,
const String& label = String());
/** Destructor. */
~AudioParameterBool();
/** Returns the parameter's current boolean value. */
bool get() const noexcept { return value >= 0.5f; }
/** Returns the parameter's current boolean value. */
operator bool() const noexcept { return get(); }
/** Changes the parameter's current value to a new boolean. */
AudioParameterBool& operator= (bool newValue);
private:
//==============================================================================
float value, defaultValue;
float getValue() const override;
void setValue (float newValue) override;
float getDefaultValue() const override;
int getNumSteps() const override;
bool isDiscrete() const override;
String getText (float, int) const override;
float getValueForText (const String&) const override;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioParameterBool)
};
} // namespace juce

+ 0
- 86
source/modules/juce_audio_processors/utilities/juce_AudioParameterChoice.h View File

@@ -1,86 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
/**
Provides a class of AudioProcessorParameter that can be used to select
an indexed, named choice from a list.
@see AudioParameterFloat, AudioParameterInt, AudioParameterBool
*/
class JUCE_API AudioParameterChoice : public AudioProcessorParameterWithID
{
public:
/** Creates a AudioParameterChoice with an ID, name, and list of items.
On creation, its value is set to the default index.
*/
AudioParameterChoice (const String& parameterID, const String& name,
const StringArray& choices,
int defaultItemIndex,
const String& label = String());
/** Destructor. */
~AudioParameterChoice();
/** Returns the current index of the selected item. */
int getIndex() const noexcept { return roundToInt (value); }
/** Returns the current index of the selected item. */
operator int() const noexcept { return getIndex(); }
/** Returns the name of the currently selected item. */
String getCurrentChoiceName() const noexcept { return choices[getIndex()]; }
/** Returns the name of the currently selected item. */
operator String() const noexcept { return getCurrentChoiceName(); }
/** Changes the selected item to a new index. */
AudioParameterChoice& operator= (int newValue);
/** Provides access to the list of choices that this parameter is working with. */
const StringArray choices;
private:
//==============================================================================
float value, defaultValue;
float getValue() const override;
void setValue (float newValue) override;
float getDefaultValue() const override;
int getNumSteps() const override;
bool isDiscrete() const override;
String getText (float, int) const override;
float getValueForText (const String&) const override;
int limitRange (int) const noexcept;
float convertTo0to1 (int) const noexcept;
int convertFrom0to1 (float) const noexcept;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioParameterChoice)
};
} // namespace juce

+ 0
- 87
source/modules/juce_audio_processors/utilities/juce_AudioParameterFloat.h View File

@@ -1,87 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
/**
A subclass of AudioProcessorParameter that provides an easy way to create a
parameter which maps onto a given NormalisableRange.
@see AudioParameterInt, AudioParameterBool, AudioParameterChoice
*/
class JUCE_API AudioParameterFloat : public AudioProcessorParameterWithID
{
public:
/** Creates a AudioParameterFloat with an ID, name, and range.
On creation, its value is set to the default value.
*/
AudioParameterFloat (const String& parameterID, const String& name,
NormalisableRange<float> normalisableRange,
float defaultValue,
const String& label = String(),
Category category = AudioProcessorParameter::genericParameter);
/** Creates a AudioParameterFloat with an ID, name, and range.
On creation, its value is set to the default value.
For control over skew factors, you can use the other
constructor and provide a NormalisableRange.
*/
AudioParameterFloat (String parameterID, String name,
float minValue,
float maxValue,
float defaultValue);
/** Destructor. */
~AudioParameterFloat();
/** Returns the parameter's current value. */
float get() const noexcept { return value; }
/** Returns the parameter's current value. */
operator float() const noexcept { return value; }
/** Changes the parameter's current value. */
AudioParameterFloat& operator= (float newValue);
/** Provides access to the parameter's range. */
NormalisableRange<float> range;
private:
//==============================================================================
float value, defaultValue;
float getValue() const override;
void setValue (float newValue) override;
float getDefaultValue() const override;
int getNumSteps() const override;
String getText (float, int) const override;
float getValueForText (const String&) const override;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioParameterFloat)
};
} // namespace juce

+ 0
- 84
source/modules/juce_audio_processors/utilities/juce_AudioParameterInt.h View File

@@ -1,84 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
/**
Provides a class of AudioProcessorParameter that can be used as an
integer value with a given range.
@see AudioParameterFloat, AudioParameterBool, AudioParameterChoice
*/
class JUCE_API AudioParameterInt : public AudioProcessorParameterWithID
{
public:
/** Creates an AudioParameterInt with an ID, name, and range.
Note that the min and max range values are inclusive.
On creation, its value is set to the default value.
*/
AudioParameterInt (const String& parameterID, const String& name,
int minValue, int maxValue,
int defaultValue,
const String& label = String());
/** Destructor. */
~AudioParameterInt();
/** Returns the parameter's current value as an integer. */
int get() const noexcept { return roundToInt (value); }
/** Returns the parameter's current value as an integer. */
operator int() const noexcept { return get(); }
/** Changes the parameter's current value to a new integer.
The value passed in will be snapped to the permitted range before being used.
*/
AudioParameterInt& operator= (int newValue);
/** Returns the parameter's range. */
Range<int> getRange() const noexcept { return Range<int> (minValue, maxValue); }
private:
//==============================================================================
int minValue, maxValue;
float value, defaultValue;
float getValue() const override;
void setValue (float newValue) override;
float getDefaultValue() const override;
int getNumSteps() const override;
String getText (float, int) const override;
float getValueForText (const String&) const override;
int limitRange (int) const noexcept;
float convertTo0to1 (int) const noexcept;
int convertFrom0to1 (float) const noexcept;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioParameterInt)
};
} // namespace juce

+ 0
- 69
source/modules/juce_audio_processors/utilities/juce_AudioProcessorParameterWithID.h View File

@@ -1,69 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
/**
This abstract base class is used by some AudioProcessorParameter helper classes.
@see AudioParameterFloat, AudioParameterInt, AudioParameterBool, AudioParameterChoice
*/
class JUCE_API AudioProcessorParameterWithID : public AudioProcessorParameter
{
public:
/** Creation of this object requires providing a name and ID which will be
constant for its lifetime.
*/
AudioProcessorParameterWithID (const String& parameterID,
const String& name,
const String& label = String(),
Category category = AudioProcessorParameter::genericParameter);
/** Destructor. */
~AudioProcessorParameterWithID();
/** Provides access to the parameter's ID string. */
const String paramID;
/** Provides access to the parameter's name. */
const String name;
/** Provides access to the parameter's label. */
const String label;
/** Provides access to the parameter's category. */
const Category category;
private:
String getName (int) const override;
String getLabel() const override;
Category getCategory() const override;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioProcessorParameterWithID)
};
} // namespace juce

+ 0
- 175
source/modules/juce_audio_processors/utilities/juce_AudioProcessorParameters.cpp View File

@@ -1,175 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
// This file contains the implementations of the various AudioParameter[XYZ] classes..
AudioProcessorParameterWithID::AudioProcessorParameterWithID (const String& idToUse,
const String& nameToUse,
const String& labelToUse,
AudioProcessorParameter::Category categoryToUse)
: paramID (idToUse), name (nameToUse), label (labelToUse), category (categoryToUse) {}
AudioProcessorParameterWithID::~AudioProcessorParameterWithID() {}
String AudioProcessorParameterWithID::getName (int maximumStringLength) const { return name.substring (0, maximumStringLength); }
String AudioProcessorParameterWithID::getLabel() const { return label; }
AudioProcessorParameter::Category AudioProcessorParameterWithID::getCategory() const { return category; }
//==============================================================================
AudioParameterFloat::AudioParameterFloat (const String& idToUse, const String& nameToUse,
NormalisableRange<float> r, float def,
const String& labelToUse, Category categoryToUse)
: AudioProcessorParameterWithID (idToUse, nameToUse, labelToUse, categoryToUse),
range (r), value (def), defaultValue (def)
{
}
AudioParameterFloat::AudioParameterFloat (String pid, String nm, float minValue, float maxValue, float def)
: AudioProcessorParameterWithID (pid, nm), range (minValue, maxValue), value (def), defaultValue (def)
{
}
AudioParameterFloat::~AudioParameterFloat() {}
float AudioParameterFloat::getValue() const { return range.convertTo0to1 (value); }
void AudioParameterFloat::setValue (float newValue) { value = range.convertFrom0to1 (newValue); }
float AudioParameterFloat::getDefaultValue() const { return range.convertTo0to1 (defaultValue); }
int AudioParameterFloat::getNumSteps() const { return AudioProcessorParameterWithID::getNumSteps(); }
float AudioParameterFloat::getValueForText (const String& text) const { return range.convertTo0to1 (text.getFloatValue()); }
String AudioParameterFloat::getText (float v, int length) const
{
String asText (range.convertFrom0to1 (v), 2);
return length > 0 ? asText.substring (0, length) : asText;
}
AudioParameterFloat& AudioParameterFloat::operator= (float newValue)
{
if (value != newValue)
setValueNotifyingHost (range.convertTo0to1 (newValue));
return *this;
}
//==============================================================================
AudioParameterInt::AudioParameterInt (const String& idToUse, const String& nameToUse,
int mn, int mx, int def,
const String& labelToUse)
: AudioProcessorParameterWithID (idToUse, nameToUse, labelToUse),
minValue (mn), maxValue (mx),
value ((float) def),
defaultValue (convertTo0to1 (def))
{
jassert (minValue < maxValue); // must have a non-zero range of values!
}
AudioParameterInt::~AudioParameterInt() {}
int AudioParameterInt::limitRange (int v) const noexcept { return jlimit (minValue, maxValue, v); }
float AudioParameterInt::convertTo0to1 (int v) const noexcept { return (limitRange (v) - minValue) / (float) (maxValue - minValue); }
int AudioParameterInt::convertFrom0to1 (float v) const noexcept { return limitRange (roundToInt ((v * (float) (maxValue - minValue)) + minValue)); }
float AudioParameterInt::getValue() const { return convertTo0to1 (roundToInt (value)); }
void AudioParameterInt::setValue (float newValue) { value = (float) convertFrom0to1 (newValue); }
float AudioParameterInt::getDefaultValue() const { return defaultValue; }
int AudioParameterInt::getNumSteps() const { return AudioProcessorParameterWithID::getNumSteps(); }
float AudioParameterInt::getValueForText (const String& text) const { return convertTo0to1 (text.getIntValue()); }
String AudioParameterInt::getText (float v, int /*length*/) const { return String (convertFrom0to1 (v)); }
AudioParameterInt& AudioParameterInt::operator= (int newValue)
{
if (get() != newValue)
setValueNotifyingHost (convertTo0to1 (newValue));
return *this;
}
//==============================================================================
AudioParameterBool::AudioParameterBool (const String& idToUse, const String& nameToUse,
bool def, const String& labelToUse)
: AudioProcessorParameterWithID (idToUse, nameToUse, labelToUse),
value (def ? 1.0f : 0.0f),
defaultValue (value)
{
}
AudioParameterBool::~AudioParameterBool() {}
float AudioParameterBool::getValue() const { return value; }
void AudioParameterBool::setValue (float newValue) { value = newValue; }
float AudioParameterBool::getDefaultValue() const { return defaultValue; }
int AudioParameterBool::getNumSteps() const { return 2; }
bool AudioParameterBool::isDiscrete() const { return true; }
float AudioParameterBool::getValueForText (const String& text) const { return text.getIntValue() != 0 ? 1.0f : 0.0f; }
String AudioParameterBool::getText (float v, int /*length*/) const { return String ((int) (v > 0.5f ? 1 : 0)); }
AudioParameterBool& AudioParameterBool::operator= (bool newValue)
{
if (get() != newValue)
setValueNotifyingHost (newValue ? 1.0f : 0.0f);
return *this;
}
//==============================================================================
AudioParameterChoice::AudioParameterChoice (const String& idToUse, const String& nameToUse,
const StringArray& c, int def, const String& labelToUse)
: AudioProcessorParameterWithID (idToUse, nameToUse, labelToUse), choices (c),
value ((float) def),
defaultValue (convertTo0to1 (def))
{
jassert (choices.size() > 0); // you must supply an actual set of items to choose from!
}
AudioParameterChoice::~AudioParameterChoice() {}
int AudioParameterChoice::limitRange (int v) const noexcept { return jlimit (0, choices.size() - 1, v); }
float AudioParameterChoice::convertTo0to1 (int v) const noexcept { return jlimit (0.0f, 1.0f, (v + 0.5f) / (float) choices.size()); }
int AudioParameterChoice::convertFrom0to1 (float v) const noexcept { return limitRange ((int) (v * (float) choices.size())); }
float AudioParameterChoice::getValue() const { return convertTo0to1 (roundToInt (value)); }
void AudioParameterChoice::setValue (float newValue) { value = (float) convertFrom0to1 (newValue); }
float AudioParameterChoice::getDefaultValue() const { return defaultValue; }
int AudioParameterChoice::getNumSteps() const { return choices.size(); }
bool AudioParameterChoice::isDiscrete() const { return true; }
float AudioParameterChoice::getValueForText (const String& text) const { return convertTo0to1 (choices.indexOf (text)); }
String AudioParameterChoice::getText (float v, int /*length*/) const { return choices [convertFrom0to1 (v)]; }
AudioParameterChoice& AudioParameterChoice::operator= (int newValue)
{
if (getIndex() != newValue)
setValueNotifyingHost (convertTo0to1 (newValue));
return *this;
}
} // namespace juce

+ 0
- 576
source/modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.cpp View File

@@ -1,576 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
struct AudioProcessorValueTreeState::Parameter : public AudioProcessorParameterWithID,
private ValueTree::Listener
{
Parameter (AudioProcessorValueTreeState& s,
const String& parameterID, const String& paramName, const String& labelText,
NormalisableRange<float> r, float defaultVal,
std::function<String (float)> valueToText,
std::function<float (const String&)> textToValue,
bool meta,
bool automatable,
bool discrete)
: AudioProcessorParameterWithID (parameterID, paramName, labelText),
owner (s), valueToTextFunction (valueToText), textToValueFunction (textToValue),
range (r), value (defaultVal), defaultValue (defaultVal),
listenersNeedCalling (true),
isMetaParam (meta),
isAutomatableParam (automatable),
isDiscreteParam (discrete)
{
state.addListener (this);
needsUpdate.set (1);
}
~Parameter()
{
// should have detached all callbacks before destroying the parameters!
jassert (listeners.size() <= 1);
}
float getValue() const override { return range.convertTo0to1 (value); }
float getDefaultValue() const override { return range.convertTo0to1 (defaultValue); }
float getValueForText (const String& text) const override
{
return range.convertTo0to1 (textToValueFunction != nullptr ? textToValueFunction (text)
: text.getFloatValue());
}
String getText (float v, int length) const override
{
return valueToTextFunction != nullptr ? valueToTextFunction (range.convertFrom0to1 (v))
: AudioProcessorParameter::getText (v, length);
}
int getNumSteps() const override
{
if (range.interval > 0)
return (static_cast<int> ((range.end - range.start) / range.interval) + 1);
return AudioProcessor::getDefaultNumParameterSteps();
}
void setValue (float newValue) override
{
newValue = range.snapToLegalValue (range.convertFrom0to1 (newValue));
if (value != newValue || listenersNeedCalling)
{
value = newValue;
listeners.call (&AudioProcessorValueTreeState::Listener::parameterChanged, paramID, value);
listenersNeedCalling = false;
needsUpdate.set (1);
}
}
void setNewState (const ValueTree& v)
{
state = v;
updateFromValueTree();
}
void setUnnormalisedValue (float newUnnormalisedValue)
{
if (value != newUnnormalisedValue)
{
const float newValue = range.convertTo0to1 (newUnnormalisedValue);
setValueNotifyingHost (newValue);
}
}
void updateFromValueTree()
{
setUnnormalisedValue (state.getProperty (owner.valuePropertyID, defaultValue));
}
void copyValueToValueTree()
{
if (state.isValid())
state.setPropertyExcludingListener (this, owner.valuePropertyID, value, owner.undoManager);
}
void valueTreePropertyChanged (ValueTree&, const Identifier& property) override
{
if (property == owner.valuePropertyID)
updateFromValueTree();
}
void valueTreeChildAdded (ValueTree&, ValueTree&) override {}
void valueTreeChildRemoved (ValueTree&, ValueTree&, int) override {}
void valueTreeChildOrderChanged (ValueTree&, int, int) override {}
void valueTreeParentChanged (ValueTree&) override {}
static Parameter* getParameterForID (AudioProcessor& processor, StringRef paramID) noexcept
{
const int numParams = processor.getParameters().size();
for (int i = 0; i < numParams; ++i)
{
AudioProcessorParameter* const ap = processor.getParameters().getUnchecked(i);
// When using this class, you must allow it to manage all the parameters in your AudioProcessor, and
// not add any parameter objects of other types!
jassert (dynamic_cast<Parameter*> (ap) != nullptr);
Parameter* const p = static_cast<Parameter*> (ap);
if (paramID == p->paramID)
return p;
}
return nullptr;
}
bool isMetaParameter() const override { return isMetaParam; }
bool isAutomatable() const override { return isAutomatableParam; }
bool isDiscrete() const override { return isDiscreteParam; }
AudioProcessorValueTreeState& owner;
ValueTree state;
ListenerList<AudioProcessorValueTreeState::Listener> listeners;
std::function<String (float)> valueToTextFunction;
std::function<float (const String&)> textToValueFunction;
NormalisableRange<float> range;
float value, defaultValue;
Atomic<int> needsUpdate;
bool listenersNeedCalling;
const bool isMetaParam, isAutomatableParam, isDiscreteParam;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Parameter)
};
//==============================================================================
AudioProcessorValueTreeState::AudioProcessorValueTreeState (AudioProcessor& p, UndoManager* um)
: processor (p),
undoManager (um),
valueType ("PARAM"),
valuePropertyID ("value"),
idPropertyID ("id"),
updatingConnections (false)
{
startTimerHz (10);
state.addListener (this);
}
AudioProcessorValueTreeState::~AudioProcessorValueTreeState() {}
AudioProcessorParameterWithID* AudioProcessorValueTreeState::createAndAddParameter (const String& paramID, const String& paramName,
const String& labelText, NormalisableRange<float> r,
float defaultVal, std::function<String (float)> valueToTextFunction,
std::function<float (const String&)> textToValueFunction,
bool isMetaParameter,
bool isAutomatableParameter,
bool isDiscreteParameter)
{
// All parameters must be created before giving this manager a ValueTree state!
jassert (! state.isValid());
#if ! JUCE_LINUX
jassert (MessageManager::getInstance()->isThisTheMessageThread());
#endif
Parameter* p = new Parameter (*this, paramID, paramName, labelText, r,
defaultVal, valueToTextFunction, textToValueFunction,
isMetaParameter, isAutomatableParameter,
isDiscreteParameter);
processor.addParameter (p);
return p;
}
void AudioProcessorValueTreeState::addParameterListener (StringRef paramID, Listener* listener)
{
if (Parameter* p = Parameter::getParameterForID (processor, paramID))
p->listeners.add (listener);
}
void AudioProcessorValueTreeState::removeParameterListener (StringRef paramID, Listener* listener)
{
if (Parameter* p = Parameter::getParameterForID (processor, paramID))
p->listeners.remove (listener);
}
Value AudioProcessorValueTreeState::getParameterAsValue (StringRef paramID) const
{
if (Parameter* p = Parameter::getParameterForID (processor, paramID))
return p->state.getPropertyAsValue (valuePropertyID, undoManager);
return Value();
}
NormalisableRange<float> AudioProcessorValueTreeState::getParameterRange (StringRef paramID) const noexcept
{
if (Parameter* p = Parameter::getParameterForID (processor, paramID))
return p->range;
return NormalisableRange<float>();
}
AudioProcessorParameterWithID* AudioProcessorValueTreeState::getParameter (StringRef paramID) const noexcept
{
return Parameter::getParameterForID (processor, paramID);
}
float* AudioProcessorValueTreeState::getRawParameterValue (StringRef paramID) const noexcept
{
if (Parameter* p = Parameter::getParameterForID (processor, paramID))
return &(p->value);
return nullptr;
}
ValueTree AudioProcessorValueTreeState::getOrCreateChildValueTree (const String& paramID)
{
ValueTree v (state.getChildWithProperty (idPropertyID, paramID));
if (! v.isValid())
{
v = ValueTree (valueType);
v.setProperty (idPropertyID, paramID, undoManager);
state.addChild (v, -1, undoManager);
}
return v;
}
void AudioProcessorValueTreeState::updateParameterConnectionsToChildTrees()
{
if (! updatingConnections)
{
ScopedValueSetter<bool> svs (updatingConnections, true, false);
const int numParams = processor.getParameters().size();
for (int i = 0; i < numParams; ++i)
{
AudioProcessorParameter* const ap = processor.getParameters().getUnchecked(i);
jassert (dynamic_cast<Parameter*> (ap) != nullptr);
Parameter* p = static_cast<Parameter*> (ap);
p->setNewState (getOrCreateChildValueTree (p->paramID));
}
}
}
void AudioProcessorValueTreeState::valueTreePropertyChanged (ValueTree& tree, const Identifier& property)
{
if (property == idPropertyID && tree.hasType (valueType) && tree.getParent() == state)
updateParameterConnectionsToChildTrees();
}
void AudioProcessorValueTreeState::valueTreeChildAdded (ValueTree& parent, ValueTree& tree)
{
if (parent == state && tree.hasType (valueType))
updateParameterConnectionsToChildTrees();
}
void AudioProcessorValueTreeState::valueTreeChildRemoved (ValueTree& parent, ValueTree& tree, int)
{
if (parent == state && tree.hasType (valueType))
updateParameterConnectionsToChildTrees();
}
void AudioProcessorValueTreeState::valueTreeRedirected (ValueTree& v)
{
if (v == state)
updateParameterConnectionsToChildTrees();
}
void AudioProcessorValueTreeState::valueTreeChildOrderChanged (ValueTree&, int, int) {}
void AudioProcessorValueTreeState::valueTreeParentChanged (ValueTree&) {}
void AudioProcessorValueTreeState::timerCallback()
{
const int numParams = processor.getParameters().size();
bool anythingUpdated = false;
for (int i = 0; i < numParams; ++i)
{
AudioProcessorParameter* const ap = processor.getParameters().getUnchecked(i);
jassert (dynamic_cast<Parameter*> (ap) != nullptr);
Parameter* p = static_cast<Parameter*> (ap);
if (p->needsUpdate.compareAndSetBool (0, 1))
{
p->copyValueToValueTree();
anythingUpdated = true;
}
}
startTimer (anythingUpdated ? 1000 / 50
: jlimit (50, 500, getTimerInterval() + 20));
}
AudioProcessorValueTreeState::Listener::Listener() {}
AudioProcessorValueTreeState::Listener::~Listener() {}
//==============================================================================
struct AttachedControlBase : public AudioProcessorValueTreeState::Listener,
public AsyncUpdater
{
AttachedControlBase (AudioProcessorValueTreeState& s, const String& p)
: state (s), paramID (p), lastValue (0)
{
state.addParameterListener (paramID, this);
}
void removeListener()
{
state.removeParameterListener (paramID, this);
}
void setNewUnnormalisedValue (float newUnnormalisedValue)
{
if (AudioProcessorParameter* p = state.getParameter (paramID))
{
const float newValue = state.getParameterRange (paramID)
.convertTo0to1 (newUnnormalisedValue);
if (p->getValue() != newValue)
p->setValueNotifyingHost (newValue);
}
}
void sendInitialUpdate()
{
if (float* v = state.getRawParameterValue (paramID))
parameterChanged (paramID, *v);
}
void parameterChanged (const String&, float newValue) override
{
lastValue = newValue;
if (MessageManager::getInstance()->isThisTheMessageThread())
{
cancelPendingUpdate();
setValue (newValue);
}
else
{
triggerAsyncUpdate();
}
}
void beginParameterChange()
{
if (AudioProcessorParameter* p = state.getParameter (paramID))
p->beginChangeGesture();
}
void endParameterChange()
{
if (AudioProcessorParameter* p = state.getParameter (paramID))
p->endChangeGesture();
}
void handleAsyncUpdate() override
{
setValue (lastValue);
}
virtual void setValue (float) = 0;
AudioProcessorValueTreeState& state;
String paramID;
float lastValue;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AttachedControlBase)
};
//==============================================================================
struct AudioProcessorValueTreeState::SliderAttachment::Pimpl : private AttachedControlBase,
private Slider::Listener
{
Pimpl (AudioProcessorValueTreeState& s, const String& p, Slider& sl)
: AttachedControlBase (s, p), slider (sl), ignoreCallbacks (false)
{
NormalisableRange<float> range (s.getParameterRange (paramID));
slider.setRange (range.start, range.end, range.interval);
slider.setSkewFactor (range.skew, range.symmetricSkew);
if (AudioProcessorParameter* param = state.getParameter (paramID))
slider.setDoubleClickReturnValue (true, range.convertFrom0to1 (param->getDefaultValue()));
sendInitialUpdate();
slider.addListener (this);
}
~Pimpl()
{
slider.removeListener (this);
removeListener();
}
void setValue (float newValue) override
{
const ScopedLock selfCallbackLock (selfCallbackMutex);
{
ScopedValueSetter<bool> svs (ignoreCallbacks, true);
slider.setValue (newValue, sendNotificationSync);
}
}
void sliderValueChanged (Slider* s) override
{
const ScopedLock selfCallbackLock (selfCallbackMutex);
if ((! ignoreCallbacks) && (! ModifierKeys::getCurrentModifiers().isRightButtonDown()))
setNewUnnormalisedValue ((float) s->getValue());
}
void sliderDragStarted (Slider*) override { beginParameterChange(); }
void sliderDragEnded (Slider*) override { endParameterChange(); }
Slider& slider;
bool ignoreCallbacks;
CriticalSection selfCallbackMutex;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Pimpl)
};
AudioProcessorValueTreeState::SliderAttachment::SliderAttachment (AudioProcessorValueTreeState& s, const String& p, Slider& sl)
: pimpl (new Pimpl (s, p, sl))
{
}
AudioProcessorValueTreeState::SliderAttachment::~SliderAttachment() {}
//==============================================================================
struct AudioProcessorValueTreeState::ComboBoxAttachment::Pimpl : private AttachedControlBase,
private ComboBox::Listener
{
Pimpl (AudioProcessorValueTreeState& s, const String& p, ComboBox& c)
: AttachedControlBase (s, p), combo (c), ignoreCallbacks (false)
{
sendInitialUpdate();
combo.addListener (this);
}
~Pimpl()
{
combo.removeListener (this);
removeListener();
}
void setValue (float newValue) override
{
const ScopedLock selfCallbackLock (selfCallbackMutex);
{
ScopedValueSetter<bool> svs (ignoreCallbacks, true);
combo.setSelectedItemIndex (roundToInt (newValue), sendNotificationSync);
}
}
void comboBoxChanged (ComboBox* comboBox) override
{
const ScopedLock selfCallbackLock (selfCallbackMutex);
if (! ignoreCallbacks)
{
beginParameterChange();
setNewUnnormalisedValue ((float) comboBox->getSelectedId() - 1.0f);
endParameterChange();
}
}
ComboBox& combo;
bool ignoreCallbacks;
CriticalSection selfCallbackMutex;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Pimpl)
};
AudioProcessorValueTreeState::ComboBoxAttachment::ComboBoxAttachment (AudioProcessorValueTreeState& s, const String& p, ComboBox& c)
: pimpl (new Pimpl (s, p, c))
{
}
AudioProcessorValueTreeState::ComboBoxAttachment::~ComboBoxAttachment() {}
//==============================================================================
struct AudioProcessorValueTreeState::ButtonAttachment::Pimpl : private AttachedControlBase,
private Button::Listener
{
Pimpl (AudioProcessorValueTreeState& s, const String& p, Button& b)
: AttachedControlBase (s, p), button (b), ignoreCallbacks (false)
{
sendInitialUpdate();
button.addListener (this);
}
~Pimpl()
{
button.removeListener (this);
removeListener();
}
void setValue (float newValue) override
{
const ScopedLock selfCallbackLock (selfCallbackMutex);
{
ScopedValueSetter<bool> svs (ignoreCallbacks, true);
button.setToggleState (newValue >= 0.5f, sendNotificationSync);
}
}
void buttonClicked (Button* b) override
{
const ScopedLock selfCallbackLock (selfCallbackMutex);
if (! ignoreCallbacks)
{
beginParameterChange();
setNewUnnormalisedValue (b->getToggleState() ? 1.0f : 0.0f);
endParameterChange();
}
}
Button& button;
bool ignoreCallbacks;
CriticalSection selfCallbackMutex;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Pimpl)
};
AudioProcessorValueTreeState::ButtonAttachment::ButtonAttachment (AudioProcessorValueTreeState& s, const String& p, Button& b)
: pimpl (new Pimpl (s, p, b))
{
}
AudioProcessorValueTreeState::ButtonAttachment::~ButtonAttachment() {}
} // namespace juce

+ 0
- 238
source/modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.h View File

@@ -1,238 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
/**
This class contains a ValueTree which is used to manage an AudioProcessor's entire state.
It has its own internal class of parameter object which are linked to values
within its ValueTree, and which are each identified by a string ID.
You can get access to the underlying ValueTree object via the state member variable,
so you can add extra properties to it as necessary.
It also provides some utility child classes for connecting parameters directly to
GUI controls like sliders.
To use:
1) Create an AudioProcessorValueTreeState, and give it some parameters using createAndAddParameter().
2) Initialise the state member variable with a type name.
*/
class JUCE_API AudioProcessorValueTreeState : private Timer,
private ValueTree::Listener
{
public:
/** Creates a state object for a given processor.
The UndoManager is optional and can be a nullptr.
After creating your state object, you should add parameters with the
createAndAddParameter() method. Note that each AudioProcessorValueTreeState
should be attached to only one processor, and must have the same lifetime as the
processor, as they will have dependencies on each other.
*/
AudioProcessorValueTreeState (AudioProcessor& processorToConnectTo,
UndoManager* undoManagerToUse);
/** Destructor. */
~AudioProcessorValueTreeState();
/** Creates and returns a new parameter object for controlling a parameter
with the given ID.
Calling this will create and add a special type of AudioProcessorParameter to the
AudioProcessor to which this state is attached.
@param parameterID A unique string ID for the new parameter
@param parameterName The name that the parameter will return from AudioProcessorParameter::getName()
@param labelText The label that the parameter will return from AudioProcessorParameter::getLabel()
@param valueRange A mapping that will be used to determine the value range which this parameter uses
@param defaultValue A default value for the parameter (in non-normalised units)
@param valueToTextFunction A function that will convert a non-normalised value to a string for the
AudioProcessorParameter::getText() method. This can be nullptr to use the
default implementation
@param textToValueFunction The inverse of valueToTextFunction
@param isMetaParameter Set this value to true if this should be a meta parameter
@param isAutomatableParameter Set this value to false if this parameter should not be automatable
@param isDiscrete Set this value to true to make this parameter take discrete values in a host.
@see AudioProcessorParameter::isDiscrete
@returns the parameter object that was created
*/
AudioProcessorParameterWithID* createAndAddParameter (const String& parameterID,
const String& parameterName,
const String& labelText,
NormalisableRange<float> valueRange,
float defaultValue,
std::function<String (float)> valueToTextFunction,
std::function<float (const String&)> textToValueFunction,
bool isMetaParameter = false,
bool isAutomatableParameter = true,
bool isDiscrete = false);
/** Returns a parameter by its ID string. */
AudioProcessorParameterWithID* getParameter (StringRef parameterID) const noexcept;
/** Returns a pointer to a floating point representation of a particular
parameter which a realtime process can read to find out its current value.
*/
float* getRawParameterValue (StringRef parameterID) const noexcept;
/** A listener class that can be attached to an AudioProcessorValueTreeState.
Use AudioProcessorValueTreeState::addParameterListener() to register a callback.
*/
struct JUCE_API Listener
{
Listener();
virtual ~Listener();
/** This callback method is called by the AudioProcessorValueTreeState when a parameter changes. */
virtual void parameterChanged (const String& parameterID, float newValue) = 0;
};
/** Attaches a callback to one of the parameters, which will be called when the parameter changes. */
void addParameterListener (StringRef parameterID, Listener* listener);
/** Removes a callback that was previously added with addParameterCallback(). */
void removeParameterListener (StringRef parameterID, Listener* listener);
/** Returns a Value object that can be used to control a particular parameter. */
Value getParameterAsValue (StringRef parameterID) const;
/** Returns the range that was set when the given parameter was created. */
NormalisableRange<float> getParameterRange (StringRef parameterID) const noexcept;
/** A reference to the processor with which this state is associated. */
AudioProcessor& processor;
/** The state of the whole processor.
This must be initialised after all calls to createAndAddParameter().
You can replace this with your own ValueTree object, and can add properties and
children to the tree. This class will automatically add children for each of the
parameter objects that are created by createAndAddParameter().
*/
ValueTree state;
/** Provides access to the undo manager that this object is using. */
UndoManager* const undoManager;
//==============================================================================
/** An object of this class maintains a connection between a Slider and a parameter
in an AudioProcessorValueTreeState.
During the lifetime of this SliderAttachment object, it keeps the two things in
sync, making it easy to connect a slider to a parameter. When this object is
deleted, the connection is broken. Make sure that your AudioProcessorValueTreeState
and Slider aren't deleted before this object!
*/
class JUCE_API SliderAttachment
{
public:
SliderAttachment (AudioProcessorValueTreeState& stateToControl,
const String& parameterID,
Slider& sliderToControl);
~SliderAttachment();
private:
struct Pimpl;
friend struct ContainerDeletePolicy<Pimpl>;
ScopedPointer<Pimpl> pimpl;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SliderAttachment)
};
//==============================================================================
/** An object of this class maintains a connection between a ComboBox and a parameter
in an AudioProcessorValueTreeState.
During the lifetime of this ComboBoxAttachment object, it keeps the two things in
sync, making it easy to connect a combo box to a parameter. When this object is
deleted, the connection is broken. Make sure that your AudioProcessorValueTreeState
and ComboBox aren't deleted before this object!
*/
class JUCE_API ComboBoxAttachment
{
public:
ComboBoxAttachment (AudioProcessorValueTreeState& stateToControl,
const String& parameterID,
ComboBox& comboBoxToControl);
~ComboBoxAttachment();
private:
struct Pimpl;
friend struct ContainerDeletePolicy<Pimpl>;
ScopedPointer<Pimpl> pimpl;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ComboBoxAttachment)
};
//==============================================================================
/** An object of this class maintains a connection between a Button and a parameter
in an AudioProcessorValueTreeState.
During the lifetime of this ButtonAttachment object, it keeps the two things in
sync, making it easy to connect a button to a parameter. When this object is
deleted, the connection is broken. Make sure that your AudioProcessorValueTreeState
and Button aren't deleted before this object!
*/
class JUCE_API ButtonAttachment
{
public:
ButtonAttachment (AudioProcessorValueTreeState& stateToControl,
const String& parameterID,
Button& buttonToControl);
~ButtonAttachment();
private:
struct Pimpl;
friend struct ContainerDeletePolicy<Pimpl>;
ScopedPointer<Pimpl> pimpl;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ButtonAttachment)
};
private:
//==============================================================================
struct Parameter;
friend struct Parameter;
ValueTree getOrCreateChildValueTree (const String&);
void timerCallback() override;
void valueTreePropertyChanged (ValueTree&, const Identifier&) override;
void valueTreeChildAdded (ValueTree&, ValueTree&) override;
void valueTreeChildRemoved (ValueTree&, ValueTree&, int) override;
void valueTreeChildOrderChanged (ValueTree&, int, int) override;
void valueTreeParentChanged (ValueTree&) override;
void valueTreeRedirected (ValueTree&) override;
void updateParameterConnectionsToChildTrees();
Identifier valueType, valuePropertyID, idPropertyID;
bool updatingConnections;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioProcessorValueTreeState)
};
} // namespace juce

Loading…
Cancel
Save