From 6ce0c2e4338885770c36df74ccf176586e41472c Mon Sep 17 00:00:00 2001 From: jules Date: Sun, 27 Jan 2013 18:28:31 +0000 Subject: [PATCH] Plugin scanning: added a custom scanner callback, and added an option to run the scan on a background thread. --- .../scanning/juce_KnownPluginList.cpp | 51 ++++++++++---- .../scanning/juce_KnownPluginList.h | 15 ++++ .../scanning/juce_PluginListComponent.cpp | 69 +++++++++++++++---- .../scanning/juce_PluginListComponent.h | 4 ++ 4 files changed, 112 insertions(+), 27 deletions(-) diff --git a/modules/juce_audio_processors/scanning/juce_KnownPluginList.cpp b/modules/juce_audio_processors/scanning/juce_KnownPluginList.cpp index 39d0775794..7c0c5c2cea 100644 --- a/modules/juce_audio_processors/scanning/juce_KnownPluginList.cpp +++ b/modules/juce_audio_processors/scanning/juce_KnownPluginList.cpp @@ -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 & typesFound, @@ -147,7 +152,11 @@ bool KnownPluginList::scanAndAddFile (const String& fileOrIdentifier, return false; OwnedArray 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 subFiles; - f.findChildFiles (subFiles, File::findFilesAndDirectories, false); + StringArray s; - for (int j = 0; j < subFiles.size(); ++j) - s.add (subFiles.getReference(j).getFullPathName()); + { + Array 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() {} diff --git a/modules/juce_audio_processors/scanning/juce_KnownPluginList.h b/modules/juce_audio_processors/scanning/juce_KnownPluginList.h index 4fdf35d5e1..41bcc16d4e 100644 --- a/modules/juce_audio_processors/scanning/juce_KnownPluginList.h +++ b/modules/juce_audio_processors/scanning/juce_KnownPluginList.h @@ -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 & result, + const String& fileOrIdentifier) = 0; + }; + + void setCustomScanner (CustomScanner* scanner); + private: //============================================================================== OwnedArray types; StringArray blacklist; + ScopedPointer scanner; JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (KnownPluginList) }; diff --git a/modules/juce_audio_processors/scanning/juce_PluginListComponent.cpp b/modules/juce_audio_processors/scanning/juce_PluginListComponent.cpp index f1dcf099b0..c4e4f8c0a1 100644 --- a/modules/juce_audio_processors/scanning/juce_PluginListComponent.cpp +++ b/modules/juce_audio_processors/scanning/juce_PluginListComponent.cpp @@ -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 (! isThreadRunning()) + { + if (doNextScan()) + startTimer (20); + } - if (scanner.scanNextFile (true) && aw.isCurrentlyModal()) + 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)) { progress = scanner.getProgress(); - startTimer (20); - } - else - { - owner.scanFinished (scanner.getFailedFiles()); + 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); } } diff --git a/modules/juce_audio_processors/scanning/juce_PluginListComponent.h b/modules/juce_audio_processors/scanning/juce_PluginListComponent.h index 1c17f8cbb7..524693f90e 100644 --- a/modules/juce_audio_processors/scanning/juce_PluginListComponent.h +++ b/modules/juce_audio_processors/scanning/juce_PluginListComponent.h @@ -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;