migrating to the latest JUCE version

This commit is contained in:
2022-11-04 23:11:33 +01:00
committed by Nikolai Rodionov
parent 4257a0f8ba
commit faf8f18333
2796 changed files with 888518 additions and 784244 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,240 +1,240 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
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
@tags{Audio}
*/
class JUCE_API KnownPluginList : public ChangeBroadcaster
{
public:
//==============================================================================
/** Creates an empty list. */
KnownPluginList();
/** Destructor. */
~KnownPluginList() override;
//==============================================================================
/** Clears the list. */
void clear();
/** Adds a type manually from its description. */
bool addType (const PluginDescription& type);
/** Removes a type. */
void removeType (const PluginDescription& type);
/** Returns the number of types currently in the list. */
int getNumTypes() const noexcept;
/** Returns a copy of the current list. */
Array<PluginDescription> getTypes() const;
/** Returns the subset of plugin types for a given format. */
Array<PluginDescription> getTypesForFormat (AudioPluginFormat&) const;
/** Looks for a type in the list which comes from this file. */
std::unique_ptr<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().
*/
std::unique_ptr<PluginDescription> getTypeForIdentifierString (const String& identifierString) const;
/** 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 the plug-in 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.
*/
static void addToMenu (PopupMenu& menu, const Array<PluginDescription>& types,
SortMethod sortMethod, const String& currentlyTickedPluginID = {});
/** Converts a menu item index that has been chosen into its index in the list.
Returns -1 if it's not an ID that was used.
@see addToMenu
*/
static int getIndexChosenByMenu (const Array<PluginDescription>& types, int menuResultCode);
//==============================================================================
/** Sorts the list. */
void sort (SortMethod method, bool forwards);
//==============================================================================
/** Creates some XML that can be used to store the state of this list. */
std::unique_ptr<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<PluginDescription> plugins;
};
/** Creates a PluginTree object representing the list of plug-ins. */
static std::unique_ptr<PluginTree> createTree (const Array<PluginDescription>& types, SortMethod sortMethod);
//==============================================================================
/** Class to define a custom plugin scanner */
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 (std::unique_ptr<CustomScanner> newScanner);
//==============================================================================
#ifndef DOXYGEN
// These methods have been deprecated! When getting the list of plugin types you should instead use
// the getTypes() method which returns a copy of the internal PluginDescription array and can be accessed
// in a thread-safe way.
[[deprecated]] PluginDescription* getType (int index) noexcept { return &types.getReference (index); }
[[deprecated]] const PluginDescription* getType (int index) const noexcept { return &types.getReference (index); }
[[deprecated]] PluginDescription** begin() noexcept { jassertfalse; return nullptr; }
[[deprecated]] PluginDescription* const* begin() const noexcept { jassertfalse; return nullptr; }
[[deprecated]] PluginDescription** end() noexcept { jassertfalse; return nullptr; }
[[deprecated]] PluginDescription* const* end() const noexcept { jassertfalse; return nullptr; }
// These methods have been deprecated in favour of their static counterparts. You should call getTypes()
// to store the plug-in list at a point in time and use it when calling these methods.
[[deprecated]] void addToMenu (PopupMenu& menu, SortMethod sortMethod, const String& currentlyTickedPluginID = {}) const;
[[deprecated]] int getIndexChosenByMenu (int menuResultCode) const;
[[deprecated]] std::unique_ptr<PluginTree> createTree (const SortMethod sortMethod) const;
#endif
private:
//==============================================================================
Array<PluginDescription> types;
StringArray blacklist;
std::unique_ptr<CustomScanner> scanner;
CriticalSection scanLock, typesArrayLock;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (KnownPluginList)
};
} // namespace juce
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
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
@tags{Audio}
*/
class JUCE_API KnownPluginList : public ChangeBroadcaster
{
public:
//==============================================================================
/** Creates an empty list. */
KnownPluginList();
/** Destructor. */
~KnownPluginList() override;
//==============================================================================
/** Clears the list. */
void clear();
/** Adds a type manually from its description. */
bool addType (const PluginDescription& type);
/** Removes a type. */
void removeType (const PluginDescription& type);
/** Returns the number of types currently in the list. */
int getNumTypes() const noexcept;
/** Returns a copy of the current list. */
Array<PluginDescription> getTypes() const;
/** Returns the subset of plugin types for a given format. */
Array<PluginDescription> getTypesForFormat (AudioPluginFormat&) const;
/** Looks for a type in the list which comes from this file. */
std::unique_ptr<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().
*/
std::unique_ptr<PluginDescription> getTypeForIdentifierString (const String& identifierString) const;
/** 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 the plug-in 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.
*/
static void addToMenu (PopupMenu& menu, const Array<PluginDescription>& types,
SortMethod sortMethod, const String& currentlyTickedPluginID = {});
/** Converts a menu item index that has been chosen into its index in the list.
Returns -1 if it's not an ID that was used.
@see addToMenu
*/
static int getIndexChosenByMenu (const Array<PluginDescription>& types, int menuResultCode);
//==============================================================================
/** Sorts the list. */
void sort (SortMethod method, bool forwards);
//==============================================================================
/** Creates some XML that can be used to store the state of this list. */
std::unique_ptr<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<PluginDescription> plugins;
};
/** Creates a PluginTree object representing the list of plug-ins. */
static std::unique_ptr<PluginTree> createTree (const Array<PluginDescription>& types, SortMethod sortMethod);
//==============================================================================
/** Class to define a custom plugin scanner */
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 (std::unique_ptr<CustomScanner> newScanner);
//==============================================================================
#ifndef DOXYGEN
// These methods have been deprecated! When getting the list of plugin types you should instead use
// the getTypes() method which returns a copy of the internal PluginDescription array and can be accessed
// in a thread-safe way.
[[deprecated]] PluginDescription* getType (int index) noexcept { return &types.getReference (index); }
[[deprecated]] const PluginDescription* getType (int index) const noexcept { return &types.getReference (index); }
[[deprecated]] PluginDescription** begin() noexcept { jassertfalse; return nullptr; }
[[deprecated]] PluginDescription* const* begin() const noexcept { jassertfalse; return nullptr; }
[[deprecated]] PluginDescription** end() noexcept { jassertfalse; return nullptr; }
[[deprecated]] PluginDescription* const* end() const noexcept { jassertfalse; return nullptr; }
// These methods have been deprecated in favour of their static counterparts. You should call getTypes()
// to store the plug-in list at a point in time and use it when calling these methods.
[[deprecated]] void addToMenu (PopupMenu& menu, SortMethod sortMethod, const String& currentlyTickedPluginID = {}) const;
[[deprecated]] int getIndexChosenByMenu (int menuResultCode) const;
[[deprecated]] std::unique_ptr<PluginTree> createTree (const SortMethod sortMethod) const;
#endif
private:
//==============================================================================
Array<PluginDescription> types;
StringArray blacklist;
std::unique_ptr<CustomScanner> scanner;
CriticalSection scanLock, typesArrayLock;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (KnownPluginList)
};
} // namespace juce

View File

@ -1,139 +1,139 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
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();
setFilesOrIdentifiersToScan (format.searchPathsForPlugins (directoriesToSearch, recursive, allowAsync));
}
PluginDirectoryScanner::~PluginDirectoryScanner()
{
list.scanFinished();
}
//==============================================================================
void PluginDirectoryScanner::setFilesOrIdentifiersToScan (const StringArray& filesOrIdentifiers)
{
filesOrIdentifiersToScan = filesOrIdentifiers;
// 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 (list, deadMansPedalFile);
nextIndex.set (filesOrIdentifiersToScan.size());
}
String PluginDirectoryScanner::getNextPluginFileThatWillBeScanned() const
{
return format.getNameOfPluginFromIdentifier (filesOrIdentifiersToScan [nextIndex.get() - 1]);
}
void PluginDirectoryScanner::updateProgress()
{
progress = (1.0f - (float) 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
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
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();
setFilesOrIdentifiersToScan (format.searchPathsForPlugins (directoriesToSearch, recursive, allowAsync));
}
PluginDirectoryScanner::~PluginDirectoryScanner()
{
list.scanFinished();
}
//==============================================================================
void PluginDirectoryScanner::setFilesOrIdentifiersToScan (const StringArray& filesOrIdentifiers)
{
filesOrIdentifiersToScan = filesOrIdentifiers;
// 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 (list, deadMansPedalFile);
nextIndex.set (filesOrIdentifiersToScan.size());
}
String PluginDirectoryScanner::getNextPluginFileThatWillBeScanned() const
{
return format.getNameOfPluginFromIdentifier (filesOrIdentifiersToScan [nextIndex.get() - 1]);
}
void PluginDirectoryScanner::updateProgress()
{
progress = (1.0f - (float) 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

View File

@ -1,138 +1,138 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
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.
@tags{Audio}
*/
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();
//==============================================================================
/** Sets a specific list of filesOrIdentifiersToScan to scan.
N.B. This list must match the format passed to the constructor.
@see AudioPluginFormat::searchPathsForPlugins
*/
void setFilesOrIdentifiersToScan (const StringArray& filesOrIdentifiersToScan);
/** 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
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
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.
@tags{Audio}
*/
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();
//==============================================================================
/** Sets a specific list of filesOrIdentifiersToScan to scan.
N.B. This list must match the format passed to the constructor.
@see AudioPluginFormat::searchPathsForPlugins
*/
void setFilesOrIdentifiersToScan (const StringArray& filesOrIdentifiersToScan);
/** 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;
std::atomic<float> progress { 0.0f };
const bool allowAsync;
void updateProgress();
void setDeadMansPedalFile (const StringArray& newContents);
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PluginDirectoryScanner)
};
} // namespace juce

View File

@ -1,143 +1,145 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
A component displaying a list of plugins, with options to scan for them,
add, remove and sort them.
@tags{Audio}
*/
class JUCE_API PluginListComponent : public Component,
public FileDragAndDropTarget,
private ChangeListener
{
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() override;
/** Changes the text in the panel's options button. */
void setOptionsButtonText (const String& newText);
/** Returns a pop-up menu that contains all the options for scanning and updating the list. */
PopupMenu createOptionsMenu();
/** Returns a menu that can be shown if a row is right-clicked, containing actions
like "remove plugin" or "show folder" etc.
*/
PopupMenu createMenuForRow (int rowNumber);
/** 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&);
/** Triggers an asynchronous scan for the given format and scans only the given files or identifiers.
@see AudioPluginFormat::searchPathsForPlugins
*/
void scanFor (AudioPluginFormat&, const StringArray& filesOrIdentifiersToScan);
/** 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*);
/** Returns the table used to display the plugin list. */
TableListBox& getTableListBox() noexcept { return table; }
/** Returns the button used to display the options menu - you can make this invisible
if you want to hide it and use some other method for showing the menu.
*/
TextButton& getOptionsButton() { return optionsButton; }
private:
//==============================================================================
AudioPluginFormatManager& formatManager;
KnownPluginList& list;
File deadMansPedalFile;
TableListBox table;
TextButton optionsButton;
PropertiesFile* propertiesToUse;
String dialogTitle, dialogText;
bool allowAsync;
int numThreads;
class TableModel;
std::unique_ptr<TableListBoxModel> tableModel;
class Scanner;
std::unique_ptr<Scanner> currentScanner;
void scanFinished (const StringArray&);
void updateList();
void removeMissingPlugins();
void removePluginItem (int index);
void resized() override;
bool isInterestedInFileDrag (const StringArray&) override;
void filesDropped (const StringArray&, int, int) override;
void changeListenerCallback (ChangeBroadcaster*) override;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PluginListComponent)
};
} // namespace juce
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
A component displaying a list of plugins, with options to scan for them,
add, remove and sort them.
@tags{Audio}
*/
class JUCE_API PluginListComponent : public Component,
public FileDragAndDropTarget,
private ChangeListener
{
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() override;
/** Changes the text in the panel's options button. */
void setOptionsButtonText (const String& newText);
/** Returns a pop-up menu that contains all the options for scanning and updating the list. */
PopupMenu createOptionsMenu();
/** Returns a menu that can be shown if a row is right-clicked, containing actions
like "remove plugin" or "show folder" etc.
*/
PopupMenu createMenuForRow (int rowNumber);
/** 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&);
/** Triggers an asynchronous scan for the given format and scans only the given files or identifiers.
@see AudioPluginFormat::searchPathsForPlugins
*/
void scanFor (AudioPluginFormat&, const StringArray& filesOrIdentifiersToScan);
/** 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*);
/** Returns the table used to display the plugin list. */
TableListBox& getTableListBox() noexcept { return table; }
/** Returns the button used to display the options menu - you can make this invisible
if you want to hide it and use some other method for showing the menu.
*/
TextButton& getOptionsButton() { return optionsButton; }
/** @internal */
void resized() override;
private:
//==============================================================================
AudioPluginFormatManager& formatManager;
KnownPluginList& list;
File deadMansPedalFile;
TableListBox table;
TextButton optionsButton;
PropertiesFile* propertiesToUse;
String dialogTitle, dialogText;
bool allowAsync;
int numThreads;
class TableModel;
std::unique_ptr<TableListBoxModel> tableModel;
class Scanner;
std::unique_ptr<Scanner> currentScanner;
void scanFinished (const StringArray&, const std::vector<String>&);
void updateList();
void removeMissingPlugins();
void removePluginItem (int index);
bool isInterestedInFileDrag (const StringArray&) override;
void filesDropped (const StringArray&, int, int) override;
void changeListenerCallback (ChangeBroadcaster*) override;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PluginListComponent)
};
} // namespace juce