| @@ -389,11 +389,7 @@ bool InternalPluginFormat::requiresUnblockedMessageThreadDuringCreation (const P | |||||
| return false; | return false; | ||||
| } | } | ||||
| void InternalPluginFormat::getAllTypes (OwnedArray<PluginDescription>& results) | |||||
| void InternalPluginFormat::getAllTypes (Array<PluginDescription>& results) | |||||
| { | { | ||||
| results.add (new PluginDescription (audioInDesc)); | |||||
| results.add (new PluginDescription (audioOutDesc)); | |||||
| results.add (new PluginDescription (midiInDesc)); | |||||
| results.add (new PluginDescription (SineWaveSynth::getPluginDescription())); | |||||
| results.add (new PluginDescription (ReverbFilter::getPluginDescription())); | |||||
| results.add (audioInDesc, audioOutDesc, midiInDesc, SineWaveSynth::getPluginDescription(), ReverbFilter::getPluginDescription()); | |||||
| } | } | ||||
| @@ -42,8 +42,7 @@ public: | |||||
| //============================================================================== | //============================================================================== | ||||
| PluginDescription audioInDesc, audioOutDesc, midiInDesc; | PluginDescription audioInDesc, audioOutDesc, midiInDesc; | ||||
| void getAllTypes (OwnedArray<PluginDescription>&); | |||||
| void getAllTypes (Array<PluginDescription>&); | |||||
| //============================================================================== | //============================================================================== | ||||
| String getName() const override { return "Internal"; } | String getName() const override { return "Internal"; } | ||||
| @@ -844,9 +844,9 @@ void GraphEditorPanel::showPopupMenu (Point<int> mousePos) | |||||
| menu->showMenuAsync ({}, | menu->showMenuAsync ({}, | ||||
| ModalCallbackFunction::create ([this, mousePos] (int r) | ModalCallbackFunction::create ([this, mousePos] (int r) | ||||
| { | { | ||||
| if (auto* mainWin = findParentComponentOfClass<MainHostWindow>()) | |||||
| if (auto* desc = mainWin->getChosenType (r)) | |||||
| createNewPlugin (*desc, mousePos); | |||||
| if (r > 0) | |||||
| if (auto* mainWin = findParentComponentOfClass<MainHostWindow>()) | |||||
| createNewPlugin (mainWin->getChosenType (r), mousePos); | |||||
| })); | })); | ||||
| } | } | ||||
| } | } | ||||
| @@ -1114,10 +1114,7 @@ struct GraphDocumentComponent::PluginListBoxModel : public ListBoxModel, | |||||
| g.setColour (rowIsSelected ? Colours::black : Colours::white); | g.setColour (rowIsSelected ? Colours::black : Colours::white); | ||||
| if (rowNumber < knownPlugins.getNumTypes()) | if (rowNumber < knownPlugins.getNumTypes()) | ||||
| g.drawFittedText (knownPlugins.getType (rowNumber)->name, | |||||
| { 0, 0, width, height - 2 }, | |||||
| Justification::centred, | |||||
| 1); | |||||
| g.drawFittedText (knownPlugins.getTypes()[rowNumber].name, { 0, 0, width, height - 2 }, Justification::centred, 1); | |||||
| g.setColour (Colours::black.withAlpha (0.4f)); | g.setColour (Colours::black.withAlpha (0.4f)); | ||||
| g.drawRect (0, height - 1, width, 1); | g.drawRect (0, height - 1, width, 1); | ||||
| @@ -1283,7 +1280,7 @@ void GraphDocumentComponent::itemDropped (const SourceDetails& details) | |||||
| // must be a valid index! | // must be a valid index! | ||||
| jassert (isPositiveAndBelow (pluginTypeIndex, pluginList.getNumTypes())); | jassert (isPositiveAndBelow (pluginTypeIndex, pluginList.getNumTypes())); | ||||
| createNewPlugin (*pluginList.getType (pluginTypeIndex), details.localPosition); | |||||
| createNewPlugin (pluginList.getTypes()[pluginTypeIndex], details.localPosition); | |||||
| } | } | ||||
| void GraphDocumentComponent::showSidePanel (bool showSettingsPanel) | void GraphDocumentComponent::showSidePanel (bool showSettingsPanel) | ||||
| @@ -111,8 +111,8 @@ MainHostWindow::MainHostWindow() | |||||
| if (auto savedPluginList = getAppProperties().getUserSettings()->getXmlValue ("pluginList")) | if (auto savedPluginList = getAppProperties().getUserSettings()->getXmlValue ("pluginList")) | ||||
| knownPluginList.recreateFromXml (*savedPluginList); | knownPluginList.recreateFromXml (*savedPluginList); | ||||
| for (auto* t : internalTypes) | |||||
| knownPluginList.addType (*t); | |||||
| for (auto& t : internalTypes) | |||||
| knownPluginList.addType (t); | |||||
| pluginSortMethod = (KnownPluginList::SortMethod) getAppProperties().getUserSettings() | pluginSortMethod = (KnownPluginList::SortMethod) getAppProperties().getUserSettings() | ||||
| ->getIntValue ("pluginSortMethod", KnownPluginList::sortByManufacturer); | ->getIntValue ("pluginSortMethod", KnownPluginList::sortByManufacturer); | ||||
| @@ -346,10 +346,9 @@ void MainHostWindow::menuItemSelected (int menuItemID, int /*topLevelMenuIndex*/ | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| if (auto* desc = getChosenType (menuItemID)) | |||||
| createPlugin (*desc, | |||||
| { proportionOfWidth (0.3f + Random::getSystemRandom().nextFloat() * 0.6f), | |||||
| proportionOfHeight (0.3f + Random::getSystemRandom().nextFloat() * 0.6f) }); | |||||
| if (knownPluginList.getIndexChosenByMenu (menuItemID) >= 0) | |||||
| createPlugin (getChosenType (menuItemID), { proportionOfWidth (0.3f + Random::getSystemRandom().nextFloat() * 0.6f), | |||||
| proportionOfHeight (0.3f + Random::getSystemRandom().nextFloat() * 0.6f) }); | |||||
| } | } | ||||
| } | } | ||||
| @@ -371,9 +370,9 @@ void MainHostWindow::addPluginsToMenu (PopupMenu& m) const | |||||
| { | { | ||||
| int i = 0; | int i = 0; | ||||
| for (auto* t : internalTypes) | |||||
| m.addItem (++i, t->name + " (" + t->pluginFormatName + ")", | |||||
| graphHolder->graph->getNodeForName (t->name) == nullptr); | |||||
| for (auto& t : internalTypes) | |||||
| m.addItem (++i, t.name + " (" + t.pluginFormatName + ")", | |||||
| graphHolder->graph->getNodeForName (t.name) == nullptr); | |||||
| } | } | ||||
| m.addSeparator(); | m.addSeparator(); | ||||
| @@ -381,12 +380,12 @@ void MainHostWindow::addPluginsToMenu (PopupMenu& m) const | |||||
| knownPluginList.addToMenu (m, pluginSortMethod); | knownPluginList.addToMenu (m, pluginSortMethod); | ||||
| } | } | ||||
| const PluginDescription* MainHostWindow::getChosenType (const int menuID) const | |||||
| PluginDescription MainHostWindow::getChosenType (const int menuID) const | |||||
| { | { | ||||
| if (menuID >= 1 && menuID < 1 + internalTypes.size()) | if (menuID >= 1 && menuID < 1 + internalTypes.size()) | ||||
| return internalTypes [menuID - 1]; | return internalTypes [menuID - 1]; | ||||
| return knownPluginList.getType (knownPluginList.getIndexChosenByMenu (menuID)); | |||||
| return knownPluginList.getTypes()[knownPluginList.getIndexChosenByMenu (menuID)]; | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -87,7 +87,7 @@ public: | |||||
| void createPlugin (const PluginDescription&, Point<int> pos); | void createPlugin (const PluginDescription&, Point<int> pos); | ||||
| void addPluginsToMenu (PopupMenu&) const; | void addPluginsToMenu (PopupMenu&) const; | ||||
| const PluginDescription* getChosenType (int menuID) const; | |||||
| PluginDescription getChosenType (int menuID) const; | |||||
| bool isDoublePrecisionProcessing(); | bool isDoublePrecisionProcessing(); | ||||
| void updatePrecisionMenuItem (ApplicationCommandInfo& info); | void updatePrecisionMenuItem (ApplicationCommandInfo& info); | ||||
| @@ -99,7 +99,7 @@ private: | |||||
| AudioDeviceManager deviceManager; | AudioDeviceManager deviceManager; | ||||
| AudioPluginFormatManager formatManager; | AudioPluginFormatManager formatManager; | ||||
| OwnedArray<PluginDescription> internalTypes; | |||||
| Array<PluginDescription> internalTypes; | |||||
| KnownPluginList knownPluginList; | KnownPluginList knownPluginList; | ||||
| KnownPluginList::SortMethod pluginSortMethod; | KnownPluginList::SortMethod pluginSortMethod; | ||||
| @@ -27,57 +27,6 @@ | |||||
| namespace juce | namespace juce | ||||
| { | { | ||||
| PluginDescription::PluginDescription() | |||||
| : uid (0), | |||||
| isInstrument (false), | |||||
| numInputChannels (0), | |||||
| numOutputChannels (0), | |||||
| hasSharedContainer (false) | |||||
| { | |||||
| } | |||||
| PluginDescription::~PluginDescription() | |||||
| { | |||||
| } | |||||
| PluginDescription::PluginDescription (const PluginDescription& other) | |||||
| : name (other.name), | |||||
| descriptiveName (other.descriptiveName), | |||||
| pluginFormatName (other.pluginFormatName), | |||||
| category (other.category), | |||||
| manufacturerName (other.manufacturerName), | |||||
| version (other.version), | |||||
| fileOrIdentifier (other.fileOrIdentifier), | |||||
| lastFileModTime (other.lastFileModTime), | |||||
| lastInfoUpdateTime (other.lastInfoUpdateTime), | |||||
| uid (other.uid), | |||||
| isInstrument (other.isInstrument), | |||||
| numInputChannels (other.numInputChannels), | |||||
| numOutputChannels (other.numOutputChannels), | |||||
| hasSharedContainer (other.hasSharedContainer) | |||||
| { | |||||
| } | |||||
| PluginDescription& PluginDescription::operator= (const PluginDescription& other) | |||||
| { | |||||
| name = other.name; | |||||
| descriptiveName = other.descriptiveName; | |||||
| pluginFormatName = other.pluginFormatName; | |||||
| category = other.category; | |||||
| manufacturerName = other.manufacturerName; | |||||
| version = other.version; | |||||
| fileOrIdentifier = other.fileOrIdentifier; | |||||
| uid = other.uid; | |||||
| isInstrument = other.isInstrument; | |||||
| lastFileModTime = other.lastFileModTime; | |||||
| lastInfoUpdateTime = other.lastInfoUpdateTime; | |||||
| numInputChannels = other.numInputChannels; | |||||
| numOutputChannels = other.numOutputChannels; | |||||
| hasSharedContainer = other.hasSharedContainer; | |||||
| return *this; | |||||
| } | |||||
| bool PluginDescription::isDuplicateOf (const PluginDescription& other) const noexcept | bool PluginDescription::isDuplicateOf (const PluginDescription& other) const noexcept | ||||
| { | { | ||||
| return fileOrIdentifier == other.fileOrIdentifier | return fileOrIdentifier == other.fileOrIdentifier | ||||
| @@ -44,10 +44,10 @@ class JUCE_API PluginDescription | |||||
| { | { | ||||
| public: | public: | ||||
| //============================================================================== | //============================================================================== | ||||
| PluginDescription(); | |||||
| PluginDescription (const PluginDescription& other); | |||||
| PluginDescription& operator= (const PluginDescription& other); | |||||
| ~PluginDescription(); | |||||
| PluginDescription() = default; | |||||
| PluginDescription (const PluginDescription& other) = default; | |||||
| PluginDescription& operator= (const PluginDescription& other) = default; | |||||
| //============================================================================== | //============================================================================== | ||||
| /** The name of the plug-in. */ | /** The name of the plug-in. */ | ||||
| @@ -96,19 +96,19 @@ public: | |||||
| @see createIdentifierString | @see createIdentifierString | ||||
| */ | */ | ||||
| int uid; | |||||
| int uid = 0; | |||||
| /** True if the plug-in identifies itself as a synthesiser. */ | /** True if the plug-in identifies itself as a synthesiser. */ | ||||
| bool isInstrument; | |||||
| bool isInstrument = false; | |||||
| /** The number of inputs. */ | /** The number of inputs. */ | ||||
| int numInputChannels; | |||||
| int numInputChannels = 0; | |||||
| /** The number of outputs. */ | /** The number of outputs. */ | ||||
| int numOutputChannels; | |||||
| int numOutputChannels = 0; | |||||
| /** True if the plug-in is part of a multi-type container, e.g. a VST Shell. */ | /** True if the plug-in is part of a multi-type container, e.g. a VST Shell. */ | ||||
| bool hasSharedContainer; | |||||
| bool hasSharedContainer = false; | |||||
| /** Returns true if the two descriptions refer to the same plug-in. | /** Returns true if the two descriptions refer to the same plug-in. | ||||
| @@ -41,26 +41,38 @@ void KnownPluginList::clear() | |||||
| } | } | ||||
| } | } | ||||
| PluginDescription* KnownPluginList::getTypeForFile (const String& fileOrIdentifier) const | |||||
| int KnownPluginList::getNumTypes() const noexcept | |||||
| { | { | ||||
| ScopedLock lock (typesArrayLock); | ScopedLock lock (typesArrayLock); | ||||
| return types.size(); | |||||
| } | |||||
| Array<PluginDescription> KnownPluginList::getTypes() const | |||||
| { | |||||
| ScopedLock lock (typesArrayLock); | |||||
| return types; | |||||
| } | |||||
| for (auto* desc : types) | |||||
| if (desc->fileOrIdentifier == fileOrIdentifier) | |||||
| return desc; | |||||
| std::unique_ptr<PluginDescription> KnownPluginList::getTypeForFile (const String& fileOrIdentifier) const | |||||
| { | |||||
| ScopedLock lock (typesArrayLock); | |||||
| for (auto& desc : types) | |||||
| if (desc.fileOrIdentifier == fileOrIdentifier) | |||||
| return std::make_unique<PluginDescription> (desc); | |||||
| return nullptr; | |||||
| return {}; | |||||
| } | } | ||||
| PluginDescription* KnownPluginList::getTypeForIdentifierString (const String& identifierString) const | |||||
| std::unique_ptr<PluginDescription> KnownPluginList::getTypeForIdentifierString (const String& identifierString) const | |||||
| { | { | ||||
| ScopedLock lock (typesArrayLock); | ScopedLock lock (typesArrayLock); | ||||
| for (auto* desc : types) | |||||
| if (desc->matchesIdentifierString (identifierString)) | |||||
| return desc; | |||||
| for (auto& desc : types) | |||||
| if (desc.matchesIdentifierString (identifierString)) | |||||
| return std::make_unique<PluginDescription> (desc); | |||||
| return nullptr; | |||||
| return {}; | |||||
| } | } | ||||
| bool KnownPluginList::addType (const PluginDescription& type) | bool KnownPluginList::addType (const PluginDescription& type) | ||||
| @@ -68,31 +80,34 @@ bool KnownPluginList::addType (const PluginDescription& type) | |||||
| { | { | ||||
| ScopedLock lock (typesArrayLock); | ScopedLock lock (typesArrayLock); | ||||
| for (auto* desc : types) | |||||
| for (auto& desc : types) | |||||
| { | { | ||||
| if (desc->isDuplicateOf (type)) | |||||
| if (desc.isDuplicateOf (type)) | |||||
| { | { | ||||
| // strange - found a duplicate plugin with different info.. | // strange - found a duplicate plugin with different info.. | ||||
| jassert (desc->name == type.name); | |||||
| jassert (desc->isInstrument == type.isInstrument); | |||||
| jassert (desc.name == type.name); | |||||
| jassert (desc.isInstrument == type.isInstrument); | |||||
| *desc = type; | |||||
| desc = type; | |||||
| return false; | return false; | ||||
| } | } | ||||
| } | } | ||||
| types.insert (0, new PluginDescription (type)); | |||||
| types.insert (0, type); | |||||
| } | } | ||||
| sendChangeMessage(); | sendChangeMessage(); | ||||
| return true; | return true; | ||||
| } | } | ||||
| void KnownPluginList::removeType (const int index) | |||||
| void KnownPluginList::removeType (const PluginDescription& type) | |||||
| { | { | ||||
| { | { | ||||
| ScopedLock lock (typesArrayLock); | ScopedLock lock (typesArrayLock); | ||||
| types.remove (index); | |||||
| for (auto& desc : types) | |||||
| if (desc.isDuplicateOf (type)) | |||||
| types.remove (&desc); | |||||
| } | } | ||||
| sendChangeMessage(); | sendChangeMessage(); | ||||
| @@ -106,16 +121,17 @@ bool KnownPluginList::isListingUpToDate (const String& fileOrIdentifier, | |||||
| ScopedLock lock (typesArrayLock); | ScopedLock lock (typesArrayLock); | ||||
| for (auto* d : types) | |||||
| if (d->fileOrIdentifier == fileOrIdentifier && formatToUse.pluginNeedsRescanning (*d)) | |||||
| for (auto& d : types) | |||||
| if (d.fileOrIdentifier == fileOrIdentifier && formatToUse.pluginNeedsRescanning (d)) | |||||
| return false; | return false; | ||||
| return true; | return true; | ||||
| } | } | ||||
| void KnownPluginList::setCustomScanner (CustomScanner* newScanner) | |||||
| void KnownPluginList::setCustomScanner (std::unique_ptr<CustomScanner> newScanner) | |||||
| { | { | ||||
| scanner.reset (newScanner); | |||||
| if (scanner != newScanner) | |||||
| scanner = std::move (newScanner); | |||||
| } | } | ||||
| bool KnownPluginList::scanAndAddFile (const String& fileOrIdentifier, | bool KnownPluginList::scanAndAddFile (const String& fileOrIdentifier, | ||||
| @@ -132,14 +148,14 @@ bool KnownPluginList::scanAndAddFile (const String& fileOrIdentifier, | |||||
| ScopedLock lock (typesArrayLock); | ScopedLock lock (typesArrayLock); | ||||
| for (auto* d : types) | |||||
| for (auto& d : types) | |||||
| { | { | ||||
| if (d->fileOrIdentifier == fileOrIdentifier && d->pluginFormatName == format.getName()) | |||||
| if (d.fileOrIdentifier == fileOrIdentifier && d.pluginFormatName == format.getName()) | |||||
| { | { | ||||
| if (format.pluginNeedsRescanning (*d)) | |||||
| if (format.pluginNeedsRescanning (d)) | |||||
| needsRescanning = true; | needsRescanning = true; | ||||
| else | else | ||||
| typesFound.add (new PluginDescription (*d)); | |||||
| typesFound.add (new PluginDescription (d)); | |||||
| } | } | ||||
| } | } | ||||
| @@ -198,7 +214,7 @@ void KnownPluginList::scanAndAddDragAndDroppedFiles (AudioPluginFormatManager& f | |||||
| if (! found) | if (! found) | ||||
| { | { | ||||
| const File f (filenameOrID); | |||||
| File f (filenameOrID); | |||||
| if (f.isDirectory()) | if (f.isDirectory()) | ||||
| { | { | ||||
| @@ -261,22 +277,22 @@ struct PluginSorter | |||||
| PluginSorter (KnownPluginList::SortMethod sortMethod, bool forwards) noexcept | PluginSorter (KnownPluginList::SortMethod sortMethod, bool forwards) noexcept | ||||
| : method (sortMethod), direction (forwards ? 1 : -1) {} | : method (sortMethod), direction (forwards ? 1 : -1) {} | ||||
| bool operator() (const PluginDescription* first, const PluginDescription* second) const | |||||
| bool operator() (const PluginDescription& first, const PluginDescription& second) const | |||||
| { | { | ||||
| int diff = 0; | int diff = 0; | ||||
| switch (method) | switch (method) | ||||
| { | { | ||||
| case KnownPluginList::sortByCategory: diff = first->category.compareNatural (second->category, false); break; | |||||
| case KnownPluginList::sortByManufacturer: diff = first->manufacturerName.compareNatural (second->manufacturerName, false); break; | |||||
| case KnownPluginList::sortByFormat: diff = first->pluginFormatName.compare (second->pluginFormatName); break; | |||||
| case KnownPluginList::sortByFileSystemLocation: diff = lastPathPart (first->fileOrIdentifier).compare (lastPathPart (second->fileOrIdentifier)); break; | |||||
| case KnownPluginList::sortByInfoUpdateTime: diff = compare (first->lastInfoUpdateTime, second->lastInfoUpdateTime); break; | |||||
| case KnownPluginList::sortByCategory: diff = first.category.compareNatural (second.category, false); break; | |||||
| case KnownPluginList::sortByManufacturer: diff = first.manufacturerName.compareNatural (second.manufacturerName, false); break; | |||||
| case KnownPluginList::sortByFormat: diff = first.pluginFormatName.compare (second.pluginFormatName); break; | |||||
| case KnownPluginList::sortByFileSystemLocation: diff = lastPathPart (first.fileOrIdentifier).compare (lastPathPart (second.fileOrIdentifier)); break; | |||||
| case KnownPluginList::sortByInfoUpdateTime: diff = compare (first.lastInfoUpdateTime, second.lastInfoUpdateTime); break; | |||||
| default: break; | default: break; | ||||
| } | } | ||||
| if (diff == 0) | if (diff == 0) | ||||
| diff = first->name.compareNatural (second->name, false); | |||||
| diff = first.name.compareNatural (second.name, false); | |||||
| return diff * direction < 0; | return diff * direction < 0; | ||||
| } | } | ||||
| @@ -303,7 +319,7 @@ void KnownPluginList::sort (const SortMethod method, bool forwards) | |||||
| { | { | ||||
| if (method != defaultOrder) | if (method != defaultOrder) | ||||
| { | { | ||||
| Array<PluginDescription*> oldOrder, newOrder; | |||||
| Array<PluginDescription> oldOrder, newOrder; | |||||
| { | { | ||||
| ScopedLock lock (typesArrayLock); | ScopedLock lock (typesArrayLock); | ||||
| @@ -313,7 +329,16 @@ void KnownPluginList::sort (const SortMethod method, bool forwards) | |||||
| newOrder.addArray (types); | newOrder.addArray (types); | ||||
| } | } | ||||
| if (oldOrder != newOrder) | |||||
| auto hasOrderChanged = [&] | |||||
| { | |||||
| for (int i = 0; i < oldOrder.size(); ++i) | |||||
| if (! oldOrder[i].isDuplicateOf (newOrder[i])) | |||||
| return true; | |||||
| return false; | |||||
| }(); | |||||
| if (hasOrderChanged) | |||||
| sendChangeMessage(); | sendChangeMessage(); | ||||
| } | } | ||||
| } | } | ||||
| @@ -327,7 +352,7 @@ std::unique_ptr<XmlElement> KnownPluginList::createXml() const | |||||
| ScopedLock lock (typesArrayLock); | ScopedLock lock (typesArrayLock); | ||||
| for (int i = types.size(); --i >= 0;) | for (int i = types.size(); --i >= 0;) | ||||
| e->prependChildElement (types.getUnchecked(i)->createXml().release()); | |||||
| e->prependChildElement (types.getUnchecked (i).createXml().release()); | |||||
| } | } | ||||
| for (auto& b : blacklist) | for (auto& b : blacklist) | ||||
| @@ -360,12 +385,12 @@ struct PluginTreeUtils | |||||
| { | { | ||||
| enum { menuIdBase = 0x324503f4 }; | enum { menuIdBase = 0x324503f4 }; | ||||
| static void buildTreeByFolder (KnownPluginList::PluginTree& tree, const Array<PluginDescription*>& allPlugins) | |||||
| static void buildTreeByFolder (KnownPluginList::PluginTree& tree, const Array<PluginDescription>& allPlugins) | |||||
| { | { | ||||
| for (auto* pd : allPlugins) | |||||
| for (auto& pd : allPlugins) | |||||
| { | { | ||||
| auto path = pd->fileOrIdentifier.replaceCharacter ('\\', '/') | |||||
| .upToLastOccurrenceOf ("/", false, false); | |||||
| auto path = pd.fileOrIdentifier.replaceCharacter ('\\', '/') | |||||
| .upToLastOccurrenceOf ("/", false, false); | |||||
| if (path.substring (1, 2) == ":") | if (path.substring (1, 2) == ":") | ||||
| path = path.substring (2); | path = path.substring (2); | ||||
| @@ -400,16 +425,16 @@ struct PluginTreeUtils | |||||
| } | } | ||||
| static void buildTreeByCategory (KnownPluginList::PluginTree& tree, | static void buildTreeByCategory (KnownPluginList::PluginTree& tree, | ||||
| const Array<PluginDescription*>& sorted, | |||||
| const Array<PluginDescription>& sorted, | |||||
| const KnownPluginList::SortMethod sortMethod) | const KnownPluginList::SortMethod sortMethod) | ||||
| { | { | ||||
| String lastType; | String lastType; | ||||
| std::unique_ptr<KnownPluginList::PluginTree> current (new KnownPluginList::PluginTree()); | |||||
| auto current = std::make_unique<KnownPluginList::PluginTree>(); | |||||
| for (auto* pd : sorted) | |||||
| for (auto& pd : sorted) | |||||
| { | { | ||||
| auto thisType = (sortMethod == KnownPluginList::sortByCategory ? pd->category | |||||
| : pd->manufacturerName); | |||||
| auto thisType = (sortMethod == KnownPluginList::sortByCategory ? pd.category | |||||
| : pd.manufacturerName); | |||||
| if (! thisType.containsNonWhitespaceChars()) | if (! thisType.containsNonWhitespaceChars()) | ||||
| thisType = "Other"; | thisType = "Other"; | ||||
| @@ -420,7 +445,7 @@ struct PluginTreeUtils | |||||
| { | { | ||||
| current->folder = lastType; | current->folder = lastType; | ||||
| tree.subFolders.add (std::move (current)); | tree.subFolders.add (std::move (current)); | ||||
| current.reset (new KnownPluginList::PluginTree()); | |||||
| current = std::make_unique<KnownPluginList::PluginTree>(); | |||||
| } | } | ||||
| lastType = thisType; | lastType = thisType; | ||||
| @@ -436,7 +461,7 @@ struct PluginTreeUtils | |||||
| } | } | ||||
| } | } | ||||
| static void addPlugin (KnownPluginList::PluginTree& tree, PluginDescription* const pd, String path) | |||||
| static void addPlugin (KnownPluginList::PluginTree& tree, PluginDescription pd, String path) | |||||
| { | { | ||||
| if (path.isEmpty()) | if (path.isEmpty()) | ||||
| { | { | ||||
| @@ -454,7 +479,7 @@ struct PluginTreeUtils | |||||
| for (int i = tree.subFolders.size(); --i >= 0;) | for (int i = tree.subFolders.size(); --i >= 0;) | ||||
| { | { | ||||
| KnownPluginList::PluginTree& subFolder = *tree.subFolders.getUnchecked(i); | |||||
| auto& subFolder = *tree.subFolders.getUnchecked (i); | |||||
| if (subFolder.folder.equalsIgnoreCase (firstSubFolder)) | if (subFolder.folder.equalsIgnoreCase (firstSubFolder)) | ||||
| { | { | ||||
| @@ -463,27 +488,26 @@ struct PluginTreeUtils | |||||
| } | } | ||||
| } | } | ||||
| auto newFolder = new KnownPluginList::PluginTree(); | |||||
| auto* newFolder = new KnownPluginList::PluginTree(); | |||||
| newFolder->folder = firstSubFolder; | newFolder->folder = firstSubFolder; | ||||
| tree.subFolders.add (newFolder); | tree.subFolders.add (newFolder); | ||||
| addPlugin (*newFolder, pd, remainingPath); | addPlugin (*newFolder, pd, remainingPath); | ||||
| } | } | ||||
| } | } | ||||
| static bool containsDuplicateNames (const Array<const PluginDescription*>& plugins, const String& name) | |||||
| static bool containsDuplicateNames (const Array<PluginDescription>& plugins, const String& name) | |||||
| { | { | ||||
| int matches = 0; | int matches = 0; | ||||
| for (int i = 0; i < plugins.size(); ++i) | |||||
| if (plugins.getUnchecked(i)->name == name) | |||||
| if (++matches > 1) | |||||
| return true; | |||||
| for (auto& p : plugins) | |||||
| if (p.name == name && ++matches > 1) | |||||
| return true; | |||||
| return false; | return false; | ||||
| } | } | ||||
| static bool addToMenu (const KnownPluginList::PluginTree& tree, PopupMenu& m, | static bool addToMenu (const KnownPluginList::PluginTree& tree, PopupMenu& m, | ||||
| const OwnedArray<PluginDescription>& allPlugins, | |||||
| const Array<PluginDescription>& allPlugins, | |||||
| const String& currentlyTickedPluginID) | const String& currentlyTickedPluginID) | ||||
| { | { | ||||
| bool isTicked = false; | bool isTicked = false; | ||||
| @@ -491,32 +515,47 @@ struct PluginTreeUtils | |||||
| for (auto* sub : tree.subFolders) | for (auto* sub : tree.subFolders) | ||||
| { | { | ||||
| PopupMenu subMenu; | PopupMenu subMenu; | ||||
| const bool isItemTicked = addToMenu (*sub, subMenu, allPlugins, currentlyTickedPluginID); | |||||
| auto isItemTicked = addToMenu (*sub, subMenu, allPlugins, currentlyTickedPluginID); | |||||
| isTicked = isTicked || isItemTicked; | isTicked = isTicked || isItemTicked; | ||||
| m.addSubMenu (sub->folder, subMenu, true, nullptr, isItemTicked, 0); | m.addSubMenu (sub->folder, subMenu, true, nullptr, isItemTicked, 0); | ||||
| } | } | ||||
| for (auto* plugin : tree.plugins) | |||||
| auto getPluginMenuIndex = [&] (const PluginDescription& d) | |||||
| { | |||||
| int i = 0; | |||||
| for (auto& p : allPlugins) | |||||
| { | |||||
| if (p.isDuplicateOf (d)) | |||||
| return i + menuIdBase; | |||||
| ++i; | |||||
| } | |||||
| return 0; | |||||
| }; | |||||
| for (auto& plugin : tree.plugins) | |||||
| { | { | ||||
| auto name = plugin->name; | |||||
| auto name = plugin.name; | |||||
| if (containsDuplicateNames (tree.plugins, name)) | if (containsDuplicateNames (tree.plugins, name)) | ||||
| name << " (" << plugin->pluginFormatName << ')'; | |||||
| name << " (" << plugin.pluginFormatName << ')'; | |||||
| const bool isItemTicked = plugin->matchesIdentifierString (currentlyTickedPluginID); | |||||
| auto isItemTicked = plugin.matchesIdentifierString (currentlyTickedPluginID); | |||||
| isTicked = isTicked || isItemTicked; | isTicked = isTicked || isItemTicked; | ||||
| m.addItem (allPlugins.indexOf (plugin) + menuIdBase, name, true, isItemTicked); | |||||
| m.addItem (getPluginMenuIndex (plugin), name, true, isItemTicked); | |||||
| } | } | ||||
| return isTicked; | return isTicked; | ||||
| } | } | ||||
| }; | }; | ||||
| KnownPluginList::PluginTree* KnownPluginList::createTree (const SortMethod sortMethod) const | |||||
| std::unique_ptr<KnownPluginList::PluginTree> KnownPluginList::createTree (const SortMethod sortMethod) const | |||||
| { | { | ||||
| Array<PluginDescription*> sorted; | |||||
| Array<PluginDescription> sorted; | |||||
| { | { | ||||
| ScopedLock lock (typesArrayLock); | ScopedLock lock (typesArrayLock); | ||||
| @@ -525,7 +564,7 @@ KnownPluginList::PluginTree* KnownPluginList::createTree (const SortMethod sortM | |||||
| std::stable_sort (sorted.begin(), sorted.end(), PluginSorter (sortMethod, true)); | std::stable_sort (sorted.begin(), sorted.end(), PluginSorter (sortMethod, true)); | ||||
| auto* tree = new PluginTree(); | |||||
| auto tree = std::make_unique<PluginTree>(); | |||||
| if (sortMethod == sortByCategory || sortMethod == sortByManufacturer || sortMethod == sortByFormat) | if (sortMethod == sortByCategory || sortMethod == sortByManufacturer || sortMethod == sortByFormat) | ||||
| { | { | ||||
| @@ -537,7 +576,7 @@ KnownPluginList::PluginTree* KnownPluginList::createTree (const SortMethod sortM | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| for (auto* p : sorted) | |||||
| for (auto& p : sorted) | |||||
| tree->plugins.add (p); | tree->plugins.add (p); | ||||
| } | } | ||||
| @@ -548,7 +587,7 @@ KnownPluginList::PluginTree* KnownPluginList::createTree (const SortMethod sortM | |||||
| void KnownPluginList::addToMenu (PopupMenu& menu, const SortMethod sortMethod, | void KnownPluginList::addToMenu (PopupMenu& menu, const SortMethod sortMethod, | ||||
| const String& currentlyTickedPluginID) const | const String& currentlyTickedPluginID) const | ||||
| { | { | ||||
| std::unique_ptr<PluginTree> tree (createTree (sortMethod)); | |||||
| auto tree = createTree (sortMethod); | |||||
| PluginTreeUtils::addToMenu (*tree, menu, types, currentlyTickedPluginID); | PluginTreeUtils::addToMenu (*tree, menu, types, currentlyTickedPluginID); | ||||
| } | } | ||||
| @@ -52,37 +52,27 @@ public: | |||||
| /** Clears the list. */ | /** Clears the list. */ | ||||
| void clear(); | void clear(); | ||||
| /** Returns the number of types currently in the list. | |||||
| @see getType | |||||
| */ | |||||
| int getNumTypes() const noexcept { return types.size(); } | |||||
| /** Adds a type manually from its description. */ | |||||
| bool addType (const PluginDescription& type); | |||||
| /** Returns one of the types. | |||||
| @see getNumTypes | |||||
| */ | |||||
| PluginDescription* getType (int index) const noexcept { return types [index]; } | |||||
| /** Removes a type. */ | |||||
| void removeType (const PluginDescription& type); | |||||
| /** Type iteration. */ | |||||
| PluginDescription** begin() const noexcept { return types.begin(); } | |||||
| /** Returns the number of types currently in the list. */ | |||||
| int getNumTypes() const noexcept; | |||||
| /** Type iteration. */ | |||||
| PluginDescription** end() const noexcept { return types.end(); } | |||||
| /** Returns a copy of the current list. */ | |||||
| Array<PluginDescription> getTypes() const; | |||||
| /** Looks for a type in the list which comes from this file. */ | /** Looks for a type in the list which comes from this file. */ | ||||
| PluginDescription* getTypeForFile (const String& fileOrIdentifier) const; | |||||
| std::unique_ptr<PluginDescription> getTypeForFile (const String& fileOrIdentifier) const; | |||||
| /** Looks for a type in the list which matches a plugin type ID. | /** Looks for a type in the list which matches a plugin type ID. | ||||
| The identifierString parameter must have been created by | The identifierString parameter must have been created by | ||||
| PluginDescription::createIdentifierString(). | PluginDescription::createIdentifierString(). | ||||
| */ | */ | ||||
| PluginDescription* getTypeForIdentifierString (const String& identifierString) const; | |||||
| /** Adds a type manually from its description. */ | |||||
| bool addType (const PluginDescription& type); | |||||
| /** Removes a type. */ | |||||
| void removeType (int index); | |||||
| std::unique_ptr<PluginDescription> getTypeForIdentifierString (const String& identifierString) const; | |||||
| /** Looks for all types that can be loaded from a given file, and adds them | /** Looks for all types that can be loaded from a given file, and adds them | ||||
| to the list. | to the list. | ||||
| @@ -153,7 +143,7 @@ public: | |||||
| Use getIndexChosenByMenu() to find out the type that was chosen. | Use getIndexChosenByMenu() to find out the type that was chosen. | ||||
| */ | */ | ||||
| void addToMenu (PopupMenu& menu, SortMethod sortMethod, | void addToMenu (PopupMenu& menu, SortMethod sortMethod, | ||||
| const String& currentlyTickedPluginID = String()) const; | |||||
| const String& currentlyTickedPluginID = {}) const; | |||||
| /** Converts a menu item index that has been chosen into its index in this list. | /** Converts a menu item index that has been chosen into its index in this list. | ||||
| Returns -1 if it's not an ID that was used. | Returns -1 if it's not an ID that was used. | ||||
| @@ -180,11 +170,11 @@ public: | |||||
| { | { | ||||
| String folder; /**< The name of this folder in the tree */ | String folder; /**< The name of this folder in the tree */ | ||||
| OwnedArray<PluginTree> subFolders; | OwnedArray<PluginTree> subFolders; | ||||
| Array<const PluginDescription*> plugins; | |||||
| Array<PluginDescription> plugins; | |||||
| }; | }; | ||||
| /** Creates a PluginTree object containing all the known plugins. */ | /** Creates a PluginTree object containing all the known plugins. */ | ||||
| PluginTree* createTree (const SortMethod sortMethod) const; | |||||
| std::unique_ptr<PluginTree> createTree (const SortMethod sortMethod) const; | |||||
| //============================================================================== | //============================================================================== | ||||
| /** Class to define a custom plugin scanner */ | /** Class to define a custom plugin scanner */ | ||||
| @@ -214,11 +204,19 @@ public: | |||||
| /** Supplies a custom scanner to be used in future scans. | /** Supplies a custom scanner to be used in future scans. | ||||
| The KnownPluginList will take ownership of the object passed in. | The KnownPluginList will take ownership of the object passed in. | ||||
| */ | */ | ||||
| void setCustomScanner (CustomScanner*); | |||||
| void setCustomScanner (std::unique_ptr<CustomScanner> newScanner); | |||||
| //============================================================================== | |||||
| // 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. | |||||
| JUCE_DEPRECATED_WITH_BODY (PluginDescription* getType (int index) const noexcept, { return &types.getReference (index); }) | |||||
| JUCE_DEPRECATED_WITH_BODY (PluginDescription** begin() const noexcept, { jassertfalse; return nullptr; }) | |||||
| JUCE_DEPRECATED_WITH_BODY (PluginDescription** end() const noexcept, { jassertfalse; return nullptr; }) | |||||
| private: | private: | ||||
| //============================================================================== | //============================================================================== | ||||
| OwnedArray<PluginDescription> types; | |||||
| Array<PluginDescription> types; | |||||
| StringArray blacklist; | StringArray blacklist; | ||||
| std::unique_ptr<CustomScanner> scanner; | std::unique_ptr<CustomScanner> scanner; | ||||
| CriticalSection scanLock, typesArrayLock; | CriticalSection scanLock, typesArrayLock; | ||||
| @@ -67,15 +67,17 @@ public: | |||||
| else if (columnId == descCol) | else if (columnId == descCol) | ||||
| text = TRANS("Deactivated after failing to initialise correctly"); | text = TRANS("Deactivated after failing to initialise correctly"); | ||||
| } | } | ||||
| else if (const PluginDescription* const desc = list.getType (row)) | |||||
| else | |||||
| { | { | ||||
| auto desc = list.getTypes()[row]; | |||||
| switch (columnId) | switch (columnId) | ||||
| { | { | ||||
| case nameCol: text = desc->name; break; | |||||
| case typeCol: text = desc->pluginFormatName; break; | |||||
| case categoryCol: text = desc->category.isNotEmpty() ? desc->category : "-"; break; | |||||
| case manufacturerCol: text = desc->manufacturerName; break; | |||||
| case descCol: text = getPluginDescription (*desc); break; | |||||
| case nameCol: text = desc.name; break; | |||||
| case typeCol: text = desc.pluginFormatName; break; | |||||
| case categoryCol: text = desc.category.isNotEmpty() ? desc.category : "-"; break; | |||||
| case manufacturerCol: text = desc.manufacturerName; break; | |||||
| case descCol: text = getPluginDescription (desc); break; | |||||
| default: jassertfalse; break; | default: jassertfalse; break; | ||||
| } | } | ||||
| @@ -238,30 +240,32 @@ void PluginListComponent::setTableModel (TableListBoxModel* model) | |||||
| bool PluginListComponent::canShowSelectedFolder() const | bool PluginListComponent::canShowSelectedFolder() const | ||||
| { | { | ||||
| if (const PluginDescription* const desc = list.getType (table.getSelectedRow())) | |||||
| return File::createFileWithoutCheckingPath (desc->fileOrIdentifier).exists(); | |||||
| return false; | |||||
| return File::createFileWithoutCheckingPath (list.getTypes()[table.getSelectedRow()].fileOrIdentifier).exists(); | |||||
| } | } | ||||
| void PluginListComponent::showSelectedFolder() | void PluginListComponent::showSelectedFolder() | ||||
| { | { | ||||
| if (canShowSelectedFolder()) | if (canShowSelectedFolder()) | ||||
| if (const PluginDescription* const desc = list.getType (table.getSelectedRow())) | |||||
| File (desc->fileOrIdentifier).getParentDirectory().startAsProcess(); | |||||
| File (list.getTypes()[table.getSelectedRow()].fileOrIdentifier).getParentDirectory().startAsProcess(); | |||||
| } | } | ||||
| void PluginListComponent::removeMissingPlugins() | void PluginListComponent::removeMissingPlugins() | ||||
| { | { | ||||
| for (int i = list.getNumTypes(); --i >= 0;) | |||||
| if (! formatManager.doesPluginStillExist (*list.getType (i))) | |||||
| list.removeType (i); | |||||
| auto types = list.getTypes(); | |||||
| for (int i = types.size(); --i >= 0;) | |||||
| { | |||||
| auto type = types.getUnchecked (i); | |||||
| if (! formatManager.doesPluginStillExist (type)) | |||||
| list.removeType (type); | |||||
| } | |||||
| } | } | ||||
| void PluginListComponent::removePluginItem (int index) | void PluginListComponent::removePluginItem (int index) | ||||
| { | { | ||||
| if (index < list.getNumTypes()) | if (index < list.getNumTypes()) | ||||
| list.removeType (index); | |||||
| list.removeType (list.getTypes()[index]); | |||||
| else | else | ||||
| list.removeFromBlacklist (list.getBlacklistedFiles() [index - list.getNumTypes()]); | list.removeFromBlacklist (list.getBlacklistedFiles() [index - list.getNumTypes()]); | ||||
| } | } | ||||