@@ -68,7 +68,7 @@ bool KnownPluginList::addType (const PluginDescription& type) | |||||
} | } | ||||
} | } | ||||
types.add (new PluginDescription (type)); | |||||
types.insert (0, new PluginDescription (type)); | |||||
sendChangeMessage(); | sendChangeMessage(); | ||||
return true; | return true; | ||||
} | } | ||||
@@ -116,6 +116,11 @@ bool KnownPluginList::isListingUpToDate (const String& fileOrIdentifier) const | |||||
return true; | return true; | ||||
} | } | ||||
void KnownPluginList::setCustomScanner (CustomScanner* newScanner) | |||||
{ | |||||
scanner = newScanner; | |||||
} | |||||
bool KnownPluginList::scanAndAddFile (const String& fileOrIdentifier, | bool KnownPluginList::scanAndAddFile (const String& fileOrIdentifier, | ||||
const bool dontRescanIfAlreadyInList, | const bool dontRescanIfAlreadyInList, | ||||
OwnedArray <PluginDescription>& typesFound, | OwnedArray <PluginDescription>& typesFound, | ||||
@@ -147,7 +152,11 @@ bool KnownPluginList::scanAndAddFile (const String& fileOrIdentifier, | |||||
return false; | return false; | ||||
OwnedArray <PluginDescription> found; | 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) | 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) | for (int i = 0; i < files.size(); ++i) | ||||
{ | { | ||||
const String filenameOrID (files[i]); | |||||
bool found = false; | |||||
for (int j = 0; j < formatManager.getNumFormats(); ++j) | for (int j = 0; j < formatManager.getNumFormats(); ++j) | ||||
{ | { | ||||
AudioPluginFormat* const format = formatManager.getFormat (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; | const int i = menuResultCode - menuIdBase; | ||||
return isPositiveAndBelow (i, types.size()) ? i : -1; | 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. */ | /** Creates a PluginTree object containing all the known plugins. */ | ||||
PluginTree* createTree (const SortMethod sortMethod) const; | 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: | private: | ||||
//============================================================================== | //============================================================================== | ||||
OwnedArray <PluginDescription> types; | OwnedArray <PluginDescription> types; | ||||
StringArray blacklist; | StringArray blacklist; | ||||
ScopedPointer<CustomScanner> scanner; | |||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (KnownPluginList) | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (KnownPluginList) | ||||
}; | }; | ||||
@@ -31,7 +31,8 @@ PluginListComponent::PluginListComponent (AudioPluginFormatManager& manager, | |||||
list (listToEdit), | list (listToEdit), | ||||
deadMansPedalFile (deadMansPedal), | deadMansPedalFile (deadMansPedal), | ||||
optionsButton ("Options..."), | optionsButton ("Options..."), | ||||
propertiesToUse (properties) | |||||
propertiesToUse (properties), | |||||
scanOnBackgroundThread (false) | |||||
{ | { | ||||
listBox.setModel (this); | listBox.setModel (this); | ||||
addAndMakeVisible (&listBox); | addAndMakeVisible (&listBox); | ||||
@@ -59,6 +60,11 @@ void PluginListComponent::setOptionsButtonText (const String& newText) | |||||
resized(); | resized(); | ||||
} | } | ||||
void PluginListComponent::setScansOnMessageThread (bool useMessageThread) noexcept | |||||
{ | |||||
scanOnBackgroundThread = ! useMessageThread; | |||||
} | |||||
void PluginListComponent::resized() | void PluginListComponent::resized() | ||||
{ | { | ||||
listBox.setBounds (0, 0, getWidth(), getHeight() - 30); | 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: | 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..."), | aw (TRANS("Scanning for plug-ins..."), | ||||
TRANS("Searching for all possible plug-in files..."), AlertWindow::NoIcon), | 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) | scanner (owner.list, format, path, true, owner.deadMansPedalFile) | ||||
{ | { | ||||
aw.addButton (TRANS("Cancel"), 0, KeyPress (KeyPress::escapeKey)); | aw.addButton (TRANS("Cancel"), 0, KeyPress (KeyPress::escapeKey)); | ||||
aw.addProgressBarComponent (progress); | aw.addProgressBarComponent (progress); | ||||
aw.enterModalState(); | aw.enterModalState(); | ||||
if (useThread) | |||||
startThread(); | |||||
startTimer (20); | startTimer (20); | ||||
} | } | ||||
~Scanner() | |||||
{ | |||||
stopThread (10000); | |||||
} | |||||
private: | private: | ||||
void timerCallback() | 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 | 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; | PluginListComponent& owner; | ||||
AlertWindow aw; | AlertWindow aw; | ||||
String progressMessage; | |||||
double progress; | double progress; | ||||
bool finished; | |||||
PluginDirectoryScanner scanner; | PluginDirectoryScanner scanner; | ||||
}; | }; | ||||
@@ -312,7 +355,7 @@ void PluginListComponent::scanFor (AudioPluginFormat* format) | |||||
propertiesToUse->saveIfNeeded(); | 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. */ | /** Changes the text in the panel's button. */ | ||||
void setOptionsButtonText (const String& newText); | void setOptionsButtonText (const String& newText); | ||||
/** Chooses whether to use the message thread or a background thread for scanning. */ | |||||
void setScansOnMessageThread (bool useMessageThread) noexcept; | |||||
//============================================================================== | //============================================================================== | ||||
/** @internal */ | /** @internal */ | ||||
void resized(); | void resized(); | ||||
@@ -83,6 +86,7 @@ private: | |||||
ListBox listBox; | ListBox listBox; | ||||
TextButton optionsButton; | TextButton optionsButton; | ||||
PropertiesFile* propertiesToUse; | PropertiesFile* propertiesToUse; | ||||
bool scanOnBackgroundThread; | |||||
class Scanner; | class Scanner; | ||||
friend class Scanner; | friend class Scanner; | ||||