Browse Source

Plugin scanning improvements: Crashed plugins are blacklisted and shown in the plugin list component.

tags/2021-05-28
jules 12 years ago
parent
commit
ac5030b909
6 changed files with 147 additions and 64 deletions
  1. +49
    -11
      modules/juce_audio_processors/scanning/juce_KnownPluginList.cpp
  2. +14
    -0
      modules/juce_audio_processors/scanning/juce_KnownPluginList.h
  3. +25
    -21
      modules/juce_audio_processors/scanning/juce_PluginDirectoryScanner.cpp
  4. +4
    -1
      modules/juce_audio_processors/scanning/juce_PluginDirectoryScanner.h
  5. +54
    -31
      modules/juce_audio_processors/scanning/juce_PluginListComponent.cpp
  6. +1
    -0
      modules/juce_audio_processors/scanning/juce_PluginListComponent.h

+ 49
- 11
modules/juce_audio_processors/scanning/juce_KnownPluginList.cpp View File

@@ -99,7 +99,7 @@ namespace
bool KnownPluginList::isListingUpToDate (const String& fileOrIdentifier) const
{
if (getTypeForFile (fileOrIdentifier) == 0)
if (getTypeForFile (fileOrIdentifier) == nullptr)
return false;
for (int i = types.size(); --i >= 0;)
@@ -121,8 +121,6 @@ bool KnownPluginList::scanAndAddFile (const String& fileOrIdentifier,
OwnedArray <PluginDescription>& typesFound,
AudioPluginFormat& format)
{
bool addedOne = false;
if (dontRescanIfAlreadyInList
&& getTypeForFile (fileOrIdentifier) != nullptr)
{
@@ -145,6 +143,9 @@ bool KnownPluginList::scanAndAddFile (const String& fileOrIdentifier,
return false;
}
if (blacklist.contains (fileOrIdentifier))
return false;
OwnedArray <PluginDescription> found;
format.findAllTypesForFile (found, fileOrIdentifier);
@@ -153,14 +154,11 @@ bool KnownPluginList::scanAndAddFile (const String& fileOrIdentifier,
PluginDescription* const desc = found.getUnchecked(i);
jassert (desc != nullptr);
if (addType (*desc))
{
addedOne = true;
typesFound.add (new PluginDescription (*desc));
}
addType (*desc);
typesFound.add (new PluginDescription (*desc));
}
return addedOne;
return found.size() > 0;
}
void KnownPluginList::scanAndAddDragAndDroppedFiles (AudioPluginFormatManager& formatManager,
@@ -196,10 +194,44 @@ void KnownPluginList::scanAndAddDragAndDroppedFiles (AudioPluginFormatManager& f
}
}
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 method_) noexcept : method (method_) {}
PluginSorter (KnownPluginList::SortMethod sortMethod) noexcept : method (sortMethod) {}
int compareElements (const PluginDescription* const first,
const PluginDescription* const second) const
@@ -248,12 +280,16 @@ XmlElement* KnownPluginList::createXml() const
for (int i = 0; i < types.size(); ++i)
e->addChildElement (types.getUnchecked(i)->createXml());
for (int i = 0; i < blacklist.size(); ++i)
e->createNewChildElement ("BLACKLISTED")->setAttribute ("id", blacklist[i]);
return e;
}
void KnownPluginList::recreateFromXml (const XmlElement& xml)
{
clear();
clearBlacklistedFiles();
if (xml.hasTagName ("KNOWNPLUGINS"))
{
@@ -261,7 +297,9 @@ void KnownPluginList::recreateFromXml (const XmlElement& xml)
{
PluginDescription info;
if (info.loadFromXml (*e))
if (e->hasTagName ("BLACKLISTED"))
blacklist.add (e->getStringAttribute ("id"));
else if (info.loadFromXml (*e))
addType (info);
}
}


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

@@ -113,6 +113,19 @@ public:
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.
*/
@@ -169,6 +182,7 @@ public:
private:
//==============================================================================
OwnedArray <PluginDescription> types;
StringArray blacklist;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (KnownPluginList);
};


+ 25
- 21
modules/juce_audio_processors/scanning/juce_PluginDirectoryScanner.cpp View File

@@ -23,14 +23,22 @@
==============================================================================
*/
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& deadMansPedalFile_)
const File& deadMansPedal)
: list (listToAddTo),
format (formatToLookFor),
deadMansPedalFile (deadMansPedalFile_),
deadMansPedalFile (deadMansPedal),
nextIndex (0),
progress (0)
{
@@ -40,7 +48,7 @@ PluginDirectoryScanner::PluginDirectoryScanner (KnownPluginList& listToAddTo,
// 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..
const StringArray crashedPlugins (getDeadMansPedalFile());
const StringArray crashedPlugins (readDeadMansPedalFile (deadMansPedalFile));
for (int i = 0; i < crashedPlugins.size(); ++i)
{
@@ -50,6 +58,8 @@ PluginDirectoryScanner::PluginDirectoryScanner (KnownPluginList& listToAddTo,
if (f == filesOrIdentifiersToScan[j])
filesOrIdentifiersToScan.move (j, -1);
}
applyBlacklistingsFromDeadMansPedal (listToAddTo, deadMansPedalFile);
}
PluginDirectoryScanner::~PluginDirectoryScanner()
@@ -71,21 +81,18 @@ bool PluginDirectoryScanner::scanNextFile (const bool dontRescanIfAlreadyInList)
OwnedArray <PluginDescription> typesFound;
// Add this plugin to the end of the dead-man's pedal list in case it crashes...
StringArray crashedPlugins (getDeadMansPedalFile());
StringArray crashedPlugins (readDeadMansPedalFile (deadMansPedalFile));
crashedPlugins.removeString (file);
crashedPlugins.add (file);
setDeadMansPedalFile (crashedPlugins);
list.scanAndAddFile (file,
dontRescanIfAlreadyInList,
typesFound,
format);
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)
if (typesFound.size() == 0 && ! list.getBlacklistedFiles().contains (file))
failedFiles.add (file);
}
@@ -101,21 +108,18 @@ bool PluginDirectoryScanner::skipNextFile()
return nextIndex < filesOrIdentifiersToScan.size();
}
StringArray PluginDirectoryScanner::getDeadMansPedalFile()
void PluginDirectoryScanner::setDeadMansPedalFile (const StringArray& newContents)
{
StringArray lines;
if (deadMansPedalFile != File::nonexistent)
{
deadMansPedalFile.readLines (lines);
lines.removeEmptyStrings();
}
return lines;
deadMansPedalFile.replaceWithText (newContents.joinIntoString ("\n"), true, true);
}
void PluginDirectoryScanner::setDeadMansPedalFile (const StringArray& newContents)
void PluginDirectoryScanner::applyBlacklistingsFromDeadMansPedal (KnownPluginList& list, const File& file)
{
if (deadMansPedalFile != File::nonexistent)
deadMansPedalFile.replaceWithText (newContents.joinIntoString ("\n"), true, true);
// 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..
const StringArray crashedPlugins (readDeadMansPedalFile (file));
for (int i = 0; i < crashedPlugins.size(); ++i)
list.addToBlacklist (crashedPlugins[i]);
}

+ 4
- 1
modules/juce_audio_processors/scanning/juce_PluginDirectoryScanner.h View File

@@ -105,6 +105,10 @@ public:
*/
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;
@@ -115,7 +119,6 @@ private:
int nextIndex;
float progress;
StringArray getDeadMansPedalFile();
void setDeadMansPedalFile (const StringArray& newContents);
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PluginDirectoryScanner);


+ 54
- 31
modules/juce_audio_processors/scanning/juce_PluginListComponent.cpp View File

@@ -43,6 +43,8 @@ PluginListComponent::PluginListComponent (AudioPluginFormatManager& manager,
setSize (400, 600);
list.addChangeListener (this);
updateList();
PluginDirectoryScanner::applyBlacklistingsFromDeadMansPedal (list, deadMansPedalFile);
}
PluginListComponent::~PluginListComponent()
@@ -60,7 +62,7 @@ void PluginListComponent::resized()
{
listBox.setBounds (0, 0, getWidth(), getHeight() - 30);
optionsButton.changeWidthToFitText (24);
optionsButton.setTopLeftPosition (8, getHeight() - 28);
optionsButton.setTopLeftPosition (0, getHeight() - 28);
}
void PluginListComponent::changeListenerCallback (ChangeBroadcaster*)
@@ -76,7 +78,7 @@ void PluginListComponent::updateList()
int PluginListComponent::getNumRows()
{
return list.getNumTypes();
return list.getNumTypes() + list.getBlacklistedFiles().size();
}
void PluginListComponent::paintListBoxItem (int row, Graphics& g, int width, int height, bool rowIsSelected)
@@ -84,46 +86,60 @@ void PluginListComponent::paintListBoxItem (int row, Graphics& g, int width, int
if (rowIsSelected)
g.fillAll (findColour (TextEditor::highlightColourId));
if (const PluginDescription* const pd = list.getType (row))
{
GlyphArrangement ga;
ga.addCurtailedLineOfText (Font (height * 0.7f, Font::bold), pd->name, 8.0f, height * 0.8f, width - 10.0f, true);
g.setColour (Colours::black);
ga.draw (g);
String name, desc;
bool isBlacklisted = false;
const Rectangle<float> bb (ga.getBoundingBox (0, -1, false));
if (row >= list.getNumTypes())
{
isBlacklisted = true;
name = list.getBlacklistedFiles() [row - list.getNumTypes()];
desc = TRANS("Deactivated after failing to initialise correctly");
}
else if (const PluginDescription* const pd = list.getType (row))
{
name = pd->name;
String desc;
desc << pd->pluginFormatName
<< (pd->isInstrument ? " instrument" : " effect")
<< " - "
<< pd->numInputChannels << (pd->numInputChannels == 1 ? " in" : " ins")
<< " / "
<< pd->numOutputChannels << (pd->numOutputChannels == 1 ? " out" : " outs");
<< " - " << pd->numInputChannels << (pd->numInputChannels == 1 ? " in" : " ins")
<< " / " << pd->numOutputChannels << (pd->numOutputChannels == 1 ? " out" : " outs");
if (pd->manufacturerName.isNotEmpty())
desc << " - " << pd->manufacturerName;
if (pd->manufacturerName.isNotEmpty()) desc << " - " << pd->manufacturerName;
if (pd->version.isNotEmpty()) desc << " - " << pd->version;
if (pd->category.isNotEmpty()) desc << " - category: '" << pd->category << '\'';
}
if (pd->version.isNotEmpty())
desc << " - " << pd->version;
if (name.isNotEmpty())
{
GlyphArrangement ga;
ga.addCurtailedLineOfText (Font (height * 0.7f, Font::bold), name, 8.0f, height * 0.8f, width - 10.0f, true);
if (pd->category.isNotEmpty())
desc << " - category: '" << pd->category << '\'';
g.setColour (isBlacklisted ? Colours::red : Colours::black);
ga.draw (g);
g.setColour (Colours::grey);
const Rectangle<float> bb (ga.getBoundingBox (0, -1, false));
ga.clear();
ga.addCurtailedLineOfText (Font (height * 0.6f), desc,
bb.getRight() + 10.0f, height * 0.8f,
jmax (bb.getRight() + 10.0f, width / 3.0f), height * 0.8f,
width - bb.getRight() - 12.0f, true);
g.setColour (isBlacklisted ? Colours::red : Colours::grey);
ga.draw (g);
}
}
static void removePluginItem (KnownPluginList& list, int index)
{
if (index < list.getNumTypes())
list.removeType (index);
else
list.removeFromBlacklist (list.getBlacklistedFiles() [index - list.getNumTypes()]);
}
void PluginListComponent::deleteKeyPressed (int lastRowSelected)
{
list.removeType (lastRowSelected);
removePluginItem (list, lastRowSelected);
}
void PluginListComponent::removeSelected()
@@ -132,15 +148,22 @@ void PluginListComponent::removeSelected()
for (int i = list.getNumTypes(); --i >= 0;)
if (selected.contains (i))
list.removeType (i);
removePluginItem (list, i);
}
void PluginListComponent::showSelectedFolder()
bool PluginListComponent::canShowSelectedFolder() const
{
const PluginDescription* const desc = list.getType (listBox.getSelectedRow());
if (const PluginDescription* const desc = list.getType (listBox.getSelectedRow()))
return File::createFileWithoutCheckingPath (desc->fileOrIdentifier).exists();
return false;
}
if (desc != nullptr && File (desc->fileOrIdentifier).existsAsFile())
File (desc->fileOrIdentifier).getParentDirectory().startAsProcess();
void PluginListComponent::showSelectedFolder()
{
if (canShowSelectedFolder())
if (const PluginDescription* const desc = list.getType (listBox.getSelectedRow()))
File (desc->fileOrIdentifier).getParentDirectory().startAsProcess();
}
void PluginListComponent::removeMissingPlugins()
@@ -180,7 +203,7 @@ void PluginListComponent::buttonClicked (Button* button)
PopupMenu menu;
menu.addItem (1, TRANS("Clear list"));
menu.addItem (5, TRANS("Remove selected plugin from list"), listBox.getNumSelectedRows() > 0);
menu.addItem (6, TRANS("Show folder containing selected plugin"), listBox.getNumSelectedRows() > 0);
menu.addItem (6, TRANS("Show folder containing selected plugin"), canShowSelectedFolder());
menu.addItem (7, TRANS("Remove any plugins whose files no longer exist"));
menu.addSeparator();
menu.addItem (2, TRANS("Sort alphabetically"));
@@ -292,7 +315,7 @@ void PluginListComponent::scanFinished (const StringArray& failedFiles)
StringArray shortNames;
for (int i = 0; i < failedFiles.size(); ++i)
shortNames.add (File (failedFiles[i]).getFileName());
shortNames.add (File::createFileWithoutCheckingPath (failedFiles[i]).getFileName());
currentScanner = nullptr; // mustn't delete this before using the failed files array


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

@@ -97,6 +97,7 @@ private:
void updateList();
void removeSelected();
void showSelectedFolder();
bool canShowSelectedFolder() const;
void removeMissingPlugins();
void buttonClicked (Button*);


Loading…
Cancel
Save