@@ -68,7 +68,7 @@ bool KnownPluginList::addType (const PluginDescription& type) | |||
} | |||
} | |||
types.add (new PluginDescription (type)); | |||
types.insert (0, new PluginDescription (type)); | |||
sendChangeMessage(); | |||
return true; | |||
} | |||
@@ -116,6 +116,11 @@ bool KnownPluginList::isListingUpToDate (const String& fileOrIdentifier) const | |||
return true; | |||
} | |||
void KnownPluginList::setCustomScanner (CustomScanner* newScanner) | |||
{ | |||
scanner = newScanner; | |||
} | |||
bool KnownPluginList::scanAndAddFile (const String& fileOrIdentifier, | |||
const bool dontRescanIfAlreadyInList, | |||
OwnedArray <PluginDescription>& typesFound, | |||
@@ -147,7 +152,11 @@ bool KnownPluginList::scanAndAddFile (const String& fileOrIdentifier, | |||
return false; | |||
OwnedArray <PluginDescription> found; | |||
format.findAllTypesForFile (found, fileOrIdentifier); | |||
if (scanner != nullptr) | |||
scanner->findPluginTypesFor (format, found, fileOrIdentifier); | |||
else | |||
format.findAllTypesForFile (found, fileOrIdentifier); | |||
for (int i = 0; i < found.size(); ++i) | |||
{ | |||
@@ -167,29 +176,39 @@ void KnownPluginList::scanAndAddDragAndDroppedFiles (AudioPluginFormatManager& f | |||
{ | |||
for (int i = 0; i < files.size(); ++i) | |||
{ | |||
const String filenameOrID (files[i]); | |||
bool found = false; | |||
for (int j = 0; j < formatManager.getNumFormats(); ++j) | |||
{ | |||
AudioPluginFormat* const format = formatManager.getFormat (j); | |||
if (scanAndAddFile (files[i], true, typesFound, *format)) | |||
return; | |||
if (format->fileMightContainThisPluginType (filenameOrID) | |||
&& scanAndAddFile (filenameOrID, true, typesFound, *format)) | |||
{ | |||
found = true; | |||
break; | |||
} | |||
} | |||
const File f (files[i]); | |||
if (f.isDirectory()) | |||
if (! found) | |||
{ | |||
StringArray s; | |||
const File f (filenameOrID); | |||
if (f.isDirectory()) | |||
{ | |||
Array<File> subFiles; | |||
f.findChildFiles (subFiles, File::findFilesAndDirectories, false); | |||
StringArray s; | |||
for (int j = 0; j < subFiles.size(); ++j) | |||
s.add (subFiles.getReference(j).getFullPathName()); | |||
} | |||
{ | |||
Array<File> subFiles; | |||
f.findChildFiles (subFiles, File::findFilesAndDirectories, false); | |||
for (int j = 0; j < subFiles.size(); ++j) | |||
s.add (subFiles.getReference(j).getFullPathName()); | |||
} | |||
scanAndAddDragAndDroppedFiles (formatManager, s, typesFound); | |||
scanAndAddDragAndDroppedFiles (formatManager, s, typesFound); | |||
} | |||
} | |||
} | |||
} | |||
@@ -485,3 +504,7 @@ int KnownPluginList::getIndexChosenByMenu (const int menuResultCode) const | |||
const int i = menuResultCode - menuIdBase; | |||
return isPositiveAndBelow (i, types.size()) ? i : -1; | |||
} | |||
//============================================================================== | |||
KnownPluginList::CustomScanner::CustomScanner() {} | |||
KnownPluginList::CustomScanner::~CustomScanner() {} |
@@ -179,10 +179,25 @@ public: | |||
/** Creates a PluginTree object containing all the known plugins. */ | |||
PluginTree* createTree (const SortMethod sortMethod) const; | |||
//============================================================================== | |||
class CustomScanner | |||
{ | |||
public: | |||
CustomScanner(); | |||
virtual ~CustomScanner(); | |||
virtual void findPluginTypesFor (AudioPluginFormat& format, | |||
OwnedArray <PluginDescription>& result, | |||
const String& fileOrIdentifier) = 0; | |||
}; | |||
void setCustomScanner (CustomScanner* scanner); | |||
private: | |||
//============================================================================== | |||
OwnedArray <PluginDescription> types; | |||
StringArray blacklist; | |||
ScopedPointer<CustomScanner> scanner; | |||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (KnownPluginList) | |||
}; | |||
@@ -31,7 +31,8 @@ PluginListComponent::PluginListComponent (AudioPluginFormatManager& manager, | |||
list (listToEdit), | |||
deadMansPedalFile (deadMansPedal), | |||
optionsButton ("Options..."), | |||
propertiesToUse (properties) | |||
propertiesToUse (properties), | |||
scanOnBackgroundThread (false) | |||
{ | |||
listBox.setModel (this); | |||
addAndMakeVisible (&listBox); | |||
@@ -59,6 +60,11 @@ void PluginListComponent::setOptionsButtonText (const String& newText) | |||
resized(); | |||
} | |||
void PluginListComponent::setScansOnMessageThread (bool useMessageThread) noexcept | |||
{ | |||
scanOnBackgroundThread = ! useMessageThread; | |||
} | |||
void PluginListComponent::resized() | |||
{ | |||
listBox.setBounds (0, 0, getWidth(), getHeight() - 30); | |||
@@ -237,42 +243,79 @@ void PluginListComponent::filesDropped (const StringArray& files, int, int) | |||
} | |||
//============================================================================== | |||
class PluginListComponent::Scanner : private Timer | |||
class PluginListComponent::Scanner : private Timer, | |||
private Thread | |||
{ | |||
public: | |||
Scanner (PluginListComponent& plc, AudioPluginFormat& format, const FileSearchPath& path) | |||
: owner (plc), | |||
Scanner (PluginListComponent& plc, | |||
AudioPluginFormat& format, | |||
const FileSearchPath& path, | |||
bool useThread) | |||
: Thread ("plugin_scan"), | |||
owner (plc), | |||
aw (TRANS("Scanning for plug-ins..."), | |||
TRANS("Searching for all possible plug-in files..."), AlertWindow::NoIcon), | |||
progress (0.0), | |||
progress (0.0), finished (false), | |||
scanner (owner.list, format, path, true, owner.deadMansPedalFile) | |||
{ | |||
aw.addButton (TRANS("Cancel"), 0, KeyPress (KeyPress::escapeKey)); | |||
aw.addProgressBarComponent (progress); | |||
aw.enterModalState(); | |||
if (useThread) | |||
startThread(); | |||
startTimer (20); | |||
} | |||
~Scanner() | |||
{ | |||
stopThread (10000); | |||
} | |||
private: | |||
void timerCallback() | |||
{ | |||
aw.setMessage (TRANS("Testing:\n\n") + scanner.getNextPluginFileThatWillBeScanned()); | |||
if (scanner.scanNextFile (true) && aw.isCurrentlyModal()) | |||
if (! isThreadRunning()) | |||
{ | |||
progress = scanner.getProgress(); | |||
startTimer (20); | |||
if (doNextScan()) | |||
startTimer (20); | |||
} | |||
if (! aw.isCurrentlyModal()) | |||
finished = true; | |||
if (finished) | |||
owner.scanFinished (scanner.getFailedFiles()); | |||
else | |||
aw.setMessage (progressMessage); | |||
} | |||
void run() | |||
{ | |||
while (doNextScan() && ! threadShouldExit()) | |||
{} | |||
} | |||
bool doNextScan() | |||
{ | |||
progressMessage = TRANS("Testing:\n\n") + scanner.getNextPluginFileThatWillBeScanned(); | |||
if (scanner.scanNextFile (true)) | |||
{ | |||
owner.scanFinished (scanner.getFailedFiles()); | |||
progress = scanner.getProgress(); | |||
return true; | |||
} | |||
finished = true; | |||
return false; | |||
} | |||
PluginListComponent& owner; | |||
AlertWindow aw; | |||
String progressMessage; | |||
double progress; | |||
bool finished; | |||
PluginDirectoryScanner scanner; | |||
}; | |||
@@ -312,7 +355,7 @@ void PluginListComponent::scanFor (AudioPluginFormat* format) | |||
propertiesToUse->saveIfNeeded(); | |||
} | |||
currentScanner = new Scanner (*this, *format, path); | |||
currentScanner = new Scanner (*this, *format, path, scanOnBackgroundThread); | |||
} | |||
} | |||
@@ -61,6 +61,9 @@ public: | |||
/** Changes the text in the panel's button. */ | |||
void setOptionsButtonText (const String& newText); | |||
/** Chooses whether to use the message thread or a background thread for scanning. */ | |||
void setScansOnMessageThread (bool useMessageThread) noexcept; | |||
//============================================================================== | |||
/** @internal */ | |||
void resized(); | |||
@@ -83,6 +86,7 @@ private: | |||
ListBox listBox; | |||
TextButton optionsButton; | |||
PropertiesFile* propertiesToUse; | |||
bool scanOnBackgroundThread; | |||
class Scanner; | |||
friend class Scanner; | |||